硕彝淄讲MyBatis的缓存
缓存的作用:通过减少IO的方式,提高程序的执行效率。
mybaits的缓存:将select语句的查询结果放到缓存(内存)中。下一次还是这条select语句的话,直接从缓存中获取,不再查数据库。一方面是减少IO,另一方面不再执行繁琐的查找算法。从而提升效率。
mybatis的缓存包括:
一级缓存:将查询的数据存储到SqlSession中
二级缓存:将查询的数据存储到SqlSessionFactory中
集成第三方缓存:比如EhCache、Memcache
缓存机制只对应select语句
一级缓存
一级缓存默认开启,不需要做任何配置。只要使用同一个SQL session对象执行同一条sql语句,就会走缓存。
@Test
public void testSelectCarById() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
// 执行sql 查询
Car car = sqlSession.selectOne("selectCarById", 2);
System.out.println(car);
// 从缓存中获取,不执行sql查询
Car car2 = sqlSession.selectOne("selectCarById", 2);
System.out.println(car2);
sqlSession.close();
}
那什么时候不走一级缓存?
SQL session对象不是同一个。
查询条件不一致,执行的不是同一个sql,也不走一级缓存
什么时候一级缓存会失效?
第一次查询和第二次查询之间发生了以下事件中的任何一件,都会让一级缓存失效:
执行了sqlSession.clearCache();方法。这是手动清空缓存。
执行了增、删、改的sql语句。不管操作哪张表,都会清空一级缓存。
二级缓存
二级缓存的范围是SqlSessionFactory。
使用二级缓存需要满足以下几个条件:
在mybatis-config.xml文件中设置,全局开启或关闭所有映射器配置文件中已配置的任何缓存。默认是true。无需设置。
在需要使用二级缓存的SqlMapper.xml文件中添加配置:
使用二级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接口
SqlSessiond对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中。此时二级缓存才可使用。
二级缓存什么时候失效?
只要两次查询之间发生了增、删、改操作。二级缓存就会失效,一级缓存也会失效。
二级缓存的相关配置
eviction:指定从缓存中移除某个对象的淘汰算法。默认采用LRU策略。
LRU:Least Recently Used。最近最少使用。优先淘汰在间隔时间内使用频率最低的对象
FIFO:First In First Out.一种先进先出的数据缓存器。先进入二级缓存的对象最先被淘汰
SOFT:软引用。淘汰软引用指向的对象。具体算法和JVM的垃圾回收算法有关。
WEAK:弱引用。淘汰弱引用指向的对象。具体算法和JVM的垃圾回收算法有关。
flushInterval:二级缓存的刷新时间间隔。单位毫秒。如果没有设置。代表不刷新缓存。只要内存足够大,一直会向二级缓存中增加数据,除非执行了增删改。
readOnly:
true:多条相同的sql语句执行之后返回的对象是同一个。性能好。但是duoxc并发可能会存在安全问题。
false:多条相同的sql语句执行之后返回的是对象的副本,调用了clone方法。性能一般,但安全。
size:二级缓存中最多可存储的Java对象数量。默认值是1024.
集成EhCache(第三方缓存)
集成EhCache是为了代替mybatis自带的二级缓存。一级缓存是无法替代的。
第一步引入依赖
第二步编写对应的配置文件
第三步设置XxxMapper.xml 中的type属性
MyBatis的逆向工程
这里的逆向工程指:根据数据库表逆向生成Java的pojo类,SqlMapper.xml文件,以及Mapper接口类等。
第一步,引入依赖、配置插件
org.mybatis.generator
mybatis-generator-maven-plugin
1.4.1
true
mysql
mysql-connector-java
8.0.30
第二步,配置generatorConfig.xml
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
connectionURL="jdbc:mysql://localhost:3306/spring6?useSSL=false&serverTimezone=UTC"
userId="root"
password="root"/>
第三步:运行逆向工程生成代码文件
无标题
其中生成的XxxExample类是用来封装查询条件的。
使用PageHelper
limit分页
mysql 中limit后面的两个数字:
第一个数字:startIndex(起始下标。下表从0开始)
第二个数字:pageSize(每页现实的记录条数)
加入一直页码pageNum和每页显示的记录条数pageSize,就可以获得第一个数字:
startIndex = (pageNum -1)* pageSize
所以分页sql可以写成 (pageNum -1)* pageSize, pageSize
当limit 后面只跟一个数字时,表示默认从下标0开始查询
比如:select * from tabeName limit 2 等价于 select * from tabeName limit 0,2
PageHelper插件
引入依赖
com.github.pagehelper
pagehelper
5.3.1
在mybatis-config.xml文件中配置插件
编写代码:
public void testSelectCarByPrice() {
SqlSession sqlSession = SqlSessionUtil.openSqlSession();
CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
// 在查询语句之前调用PageHelper.startPage方法,传入页码和每页显示的记录数
PageHelper.startPage(2, 5);
List cars = carMapper.selectList("selectCarByPrice", 20.0);
// 第二个参数5表示导航页的数量,导航页是指在分页结果中显示的页码数量,通常用于前端页面的分页导航
PageInfo pageInfo = new PageInfo<>(cars, 5);
System.out.println("总记录数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
for (Car car : cars) {
System.out.println(car);
}
sqlSession.close();
}
MyBatis注解式开发
注解式开发可以减少sql映射文件得到的配置。但是这种方法会给sql语句的维护带来成本。如果你需要做一些很复杂的操作,最好使用xml来映射语句。
原则:简单sql可以使用注解,复杂sql使用xml。
@Insert注解
注意:以下代码写在XxxMapper的接口文件文件中。
@Insert("insert into clazz values (#{id}, #{name})")
int insertClazz(Clazz clazz);
@Delete注解
@Delete("delete from clazz where id = #{id}")
int deleteClazzById(int id);
@Update注解
@Update("update clazz set name = #{name} where id = #{id}")
int updateClazz(Clazz clazz);
@Select注解
@Select("select * from clazz where id = #{id}")
Clazz selectClazzById(int id);
@Results注解
@Select("select * from clazz where id = #{id}")
// 如果查询结果的列名和属性名不一致,需要使用@Results注解进行映射
@Results({
@Result(property = "id", column = "id"),
@Result(property = "name", column = "name")
})
Clazz selectClazzById(int id);