目录
1. mybatis映射文件处理特殊字符.
<!--
第一种:转义标签 <
第二种: <![CDATA[sql]]>
-->
<select id="findByMaxMin" resultType="com.ykq.entity.Account">
<![CDATA[select * from account where id >#{min} and id <#{max}]]>
</select>
2. mybatis完成模糊查询。
select * from 表名 where 列名 like '%a%'
(1)使用字符串函数 完成拼接 concat
<select id="findByLike" resultType="com.cmw.entity.Account">
select * from account where name like concat('%',#{name},'%')
</select>
运行结果:
(2) 使用${}
<select id="findByLike" resultType="com.cmw.entity.Account">
select * from account where name like '%${name}%'
</select>
查询结果:
${}实际上是字符串拼接,它不能防止sql注入
而#{}它是预编译,它可以防止sql注入问题,#{}实际使用的PreparedStatement.
3. 联表查询
多对一 : 从多的一方来查询一的一方。
班级表:
学生表:
根据学生id查询学生信息并携带班级信息。
select * from tb_stu s join tb_class c on s.class_id=c.cid where tb_id=#{id}
Student实体类:
package com.cmw.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author 86151
* @Create 2022/6/1 - 16:23
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
private String name;
private int age;
private String sex;
private Integer classId;
//学生所属的班级
private Clazz clazz;
}
clazz实体类:
package com.cmw.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author 86151
* @Create 2022/6/2 - 16:37
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Clazz {
private Integer cid;
private String cname;
}
studentMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cmw.dao.StudentDao">
<resultMap id="baseMap" type="com.cmw.entity.Student">
<id column="tb_id" property="id"/>
<result column="tb_name" property="name"/>
<result column="tb_age" property="age"/>
<result column="class_id" property="classId"/>
<!--
association:表示1的一方
property:属性名
javaType:该属性名对应的数据类型
-->
<association property="clazz" javaType="com.cmw.entity.Clazz">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</association>
</resultMap>
<sql id="a">
tb_id,tb_name,tb_age,sex,class_id,c.cid cid,cname
</sql>
<select id="findStudentById" resultMap="baseMap">
select <include refid="a"/> from tb_stu s join tb_class c on s.class_id=c.cid where tb_id=#{id}
</select>
</mapper>
另一种方法:返回类型就map封装
//根据学生编号查询学员信息以及班级信息
public Map findById(Integer id);
<!--key:value-->
<select id="findById" resultType="java.util.Map">
select <include refid="aa"/> from tb_stu s join tb_class c on s.class_id=c.id where s.id=#{id}
</select>
4.分页插件PageHelper.
分页的sql语句如下:
select * from 表名 [where 条件] limit (page-1)*pageSize, pageSize;
page: 当前页码 pageSize: 每页显示的条数。
如何使用:
(1)在pom.xml中 引入pageHelper的jar包
<!--引入pageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.11</version>
</dependency>
(2)mybatis.xml中设置pageHelper的拦截器
<plugins>
<!--pageHelper的拦截器插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
(3)运行pageHelper
//查询所有
@Test
public void testFindAll() throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
UserDao userDao = session.getMapper(UserDao.class);//获取接口的映射类
//设置分页属性PageNum:显示第几页 PageSize:每页显示的条数
PageHelper.startPage(2,3);
List<User> list = userDao.findAll();
//把查询的结果封装到PageInfo类中
PageInfo<User> pageInfo=new PageInfo<>(list);
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页码对应的数据:"+pageInfo.getList());
session.commit();
session.close();
}
运行结果:
5. generator—mybatis代码生成器
作用: 根据数据库表自动生成实体类,dao和xml映射文件。实现简单的增删改查。网站是:MyBatis Generator Core – Introduction to MyBatis Generator/
(1)在pom.xml中,引入mybatis-generator的依赖jar包。
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
(2)在整体项目下创建generator的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--找到MySQL的jar包驱动位置-->
<classPathEntry location="D:\repMaven\mysql\mysql-connector-java\8.0.28\mysql-connector-java-8.0.28.jar" />
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--去除注释-->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据源的配置信息-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!--java实体类的配置-->
<javaModelGenerator targetPackage="com.cmw.entity" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--映射文件的配置-->
<sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--dao数据访问层的配置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.cmw.dao" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!--数据库和实体的映射关系
schema:数据库名称
tableName:表名
domainObjectName:实体类名
enableUpdateByExample:是否生成复杂的修改操作
-->
<table schema="mybatis" tableName="tbl_user" domainObjectName="Users"
enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false">
</table>
<table schema="mybatis" tableName="tb_stu" domainObjectName="Student"
enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false">
</table>
</context>
</generatorConfiguration>
(3)运行配置文件,自动生成mybatis代码
package com.cmw;
import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @Author 86151
* @Create 2022/6/6 - 16:03
*/
public class Test1 {
//运行,实现代码生成
@Test
public void test1() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
6. mybatis的缓存
缓存是存在于内存中的临时数据。
mysql数据库中的数据存在--表-->磁盘上。查询---程序IO读取磁盘的数据---添加--io向磁盘添加数据。
使用缓存减少和数据库的交互次数,提高执行效率。
适合放入缓存的数据:
1)经常查询并且不经常改变的;
2)数据的正确与否对最终结果影响不大的;
不适合放入缓存的数据:
1)经常改变的数据;
2)数据的正确与否对最终结果影响很大的;---数据安全性要求不高。 例如:商品的库存,银行的汇率,股市的牌价;
6.1 mybatis支持两种缓存
(1)一级缓存----基于SqlSession级别的缓存。默认一级缓存是开启的,不能关闭。
(2)二级缓存--基于SqlSessionFactory级别的缓存,可以做到多个SqlSession共享数据。默认它是关闭。需要手动开启。
注:查询顺序: 二级缓存----一级缓存----数据库。
6.1.1 测试一级缓存
package com.cmw;
import com.cmw.dao.UsersMapper;
import com.cmw.entity.Users;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.Reader;
/**
* @Author 86151
* @Create 2022/6/6 - 20:08
*/
public class TestUsersMapper {
@Test
public void test1()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
UsersMapper mapper = session.getMapper(UsersMapper.class);
//一级缓存作用域是sqlSession级别的,同一个sqlSession中执行相同的SQL查询(相同的SQL和参数),
// 第一次会查询数据库并存到缓存中,第二次从一级缓存中取
//底层就是一个hashmap (2,users)
Users users = mapper.selectByPrimaryKey(3);
System.out.println(users);
Users users1=mapper.selectByPrimaryKey(3);
System.out.println(users1);
}
//基于sqlSession完成的一级缓存
//查询结果是两条SQL语句,因为sqlSession不是同一个,一级缓存不能命中,查询两次
@Test
public void test2()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
UsersMapper mapper = session.getMapper(UsersMapper.class);
Users users = mapper.selectByPrimaryKey(3);
System.out.println(users);
session.close();
//开启新的sqlSession
SqlSession session1 = factory.openSession();
UsersMapper mapper1 = session1.getMapper(UsersMapper.class);
Users users1=mapper1.selectByPrimaryKey(3);
System.out.println(users1);
}
}
test2的测试结果:
6.1.2 演示二级缓存
(1)在mybatis.xml中开启二级缓存,写在configuration内部的最上方
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
(2)在映射文件UserMapper.xml中使用二级缓存
<!--使用二级缓存 这里面的所有查询都使用了二级缓存-->
<cache/>
(3)实体要实现序列化接口,写了不会有问题,不写可能会报错
(4)测试二级缓存
//基于SqlSessionFactory的二级缓存
//结果是一条SQL语句,因为查询的结果放入一级缓存和二级缓存,二级缓存命中则不再发送查询语句
@Test
public void test3()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = factory.openSession();
UsersMapper mapper = session.getMapper(UsersMapper.class);
Users users = mapper.selectByPrimaryKey(3);
System.out.println(users);
session.close();
//开启新的sqlSession
SqlSession session1 = factory.openSession();
UsersMapper mapper1 = session1.getMapper(UsersMapper.class);
Users users1=mapper1.selectByPrimaryKey(3);
System.out.println(users1);
}
test3的结果: