MyBatis缓存与延迟加载机制
本文最后更新于:1 年前
MyBatis是基于JDBC的封装,使数据库操作更加便捷;MyBatis除了对JDBC操作步骤进行封装之外也对其性能进行了优化:
- 在MyBatis引入缓存机制,用于提升MyBatis的检索效率;
- 在MyBatis引入延迟加载机制,用于减少对数据库不必要的访问。
MyBatis缓存
MyBatis缓存分为一级缓存和二级缓存。
缓存工作原理
所谓缓存,就是存储数据的内存。
一级缓存
一级缓存也叫做 SqlSession 级缓存,即为每个 SqlSession 单独分配的缓存内存,无需手动开启可直接使用;多个 SqlSession 的缓存是不共享的。
特性
如果多次查询使用的是同一个SqlSession对象,则第一次查询之后数据会存放到缓存,后续的查询则直接访问缓存中存储的数据;
如果第一次查询完成之后,对查询出的对象进行修改(此修改会影响到缓存),第二次查询会直接访问缓存,造成第二次查询的结果与数据库不一致;
当我们进行在查询时想要跳过缓存直接查询数据库,则可以通过sqlSession.clearCache();来清除当前SqlSession的缓存;
如果第一次查询之后第二查询之前,使用当前的sqlsession执行了修改操作,此修改操作会使第一次查询并缓存的数据失效,因此第二次查询会再次访问数据库。
案例分析
二级缓存
二级缓存也称为 SqlSessionFactory 级缓存,通过同一个 factory 对象获取的 Sqlsession 可以共享二级缓存。在应用服务器中SqlSessionFactory是单例的,因此我们二级缓存可以实现全局共享。
特性特性:
二级缓存默认没有开启,需要在 mybatis-config.xml 中的 settings 标签开启;
二级缓存只能缓存实现序列化接口的对象。
步骤案例
在 mybatis-config.xml 开启使用二级缓存
1
2
3<settings>
<setting name="cacheEnabled" value="true"/>
</settings>在需要使用二级缓存的 Mapper 文件中配置 cache 标签使用功能二级缓存
1
<cache></cache>
让被缓存的实体类实现序列化接口
1
2
3
4
5
6
7
8
9
10
11@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member implements Serializable {
private int memberId;
private String memberNick;
private String memberGender;
private int memberAge;
private String memberCity;
}测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Test
public void testQueryMemberById(){
SqlSessionFactory factory =MyBatisUtil.getSqlSessionFactory();
// 1.多个SqlSession对象必须来自于同一个SqlSessionFactory
SqlSession sqlSession1 = factory.openSession(true);
SqlSession sqlSession2 = factory.openSession(true);
System.out.println(sqlSession1 == sqlSession2);
MemberDAO memberDAO1 = sqlSession1.getMapper(MemberDAO.class);
Member member1 = memberDAO1.queryMemberById(1);
System.out.println(member1);
sqlSession1.commit();
//2.第一次查询之后执行sqlSession1.commit(),才会将当前sqlsession的查询结果缓存到二级缓存
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
MemberDAO memberDAO2 = sqlSession2.getMapper(MemberDAO.class);
Member member2 =memberDAO2.queryMemberById(1);
System.out.println(member2);
}
查询操作的缓存开关
1 |
|
延迟加载
如果在MyBatis开启了延迟加载,在执行了子查询(至少查询两次及以上)时,默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需使用子查询结果,则子查询不会执行。
开启延迟加载
1 |
|
测试代码
1 |
|
运行日志
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!