========================= MyBatis缓存机制之二级缓存 ========================= 与由SqlSession维护的一级即会话级缓存不同: - 二级缓存由SqlSessionFactory维护,称为会话工厂级缓存; - SqlSessionFactory本身就是一个单例,一个进程只有一个; - 多个服务(Service)线程共享同一个二级缓存。 _线程_ _线程_ / \ / \ Service1 Service2 SqlSessionFactory Database 空 20 20 <----------- 20 <- 20 20 <- 20 20 21 -----------> 空 -> 21 21 <- 21 <- 21 \_________ ___________/ \ / 一致 二级缓存具有如下特性: - 二级缓存默认关闭,需要在mybatis-config.xml文件的settings标签中手动开启 ... ... - 需要在Mapper文件中通过cache标签设置二级缓存,该标签包含如下属性: - eviction:清除策略 - LRU(默认):优先清除闲置时间最长的对象 - FIFO:按进入缓存的顺序清除缓存中的对象 - SOFT:基于垃圾回收器状态和软引用规则清除对象 - WEAK:基于垃圾回收器状态和弱引用规则清除对象 - flushInterval:刷新间隔毫秒值,不设置(默认)表示仅在调用语句时刷新 - size:最多缓存对象或列表的引用数,默认1024 - readOnly:缓存中的对象是否只读 - true:只读,得到的是缓冲中对象的引用,速度快 - false(默认):可写,得到的是缓存中将对象的拷贝,慢但是安全 - 二级缓存只能缓存实现了序列化接口的实体类对象 1 开启二级缓存 在mybatis-config.xml文件中添加: ... ... 2 设置二级缓存 在MemberMapper.xml文件中添加: ... ... 3 实现序列化接口 @Data @AllArgsConstructor @NoArgsConstructor @ToString public class Member implements Serializable { ... } 4 编写测试用例 public class MemberDaoTest { ... @Test public void testSearchById() { Member member; SqlSession session1 = MyBatisUtil.getFactory().openSession(); MemberDao dao1 = session1.getMapper(MemberDao.class); System.out.println("\n第一次查询..."); System.out.println(member = dao1.searchById(1)); session1.commit(); // 这里必须提交! SqlSession session2 = MyBatisUtil.getFactory().openSession(); MemberDao dao2 = session2.getMapper(MemberDao.class); System.out.println("\n第二次查询..."); System.out.println(dao2.searchById(1)); dao1.modifyAge(member.getId(), member.getAge() + 1); session1.commit(); System.out.println("\n第三次查询..."); System.out.println(dao2.searchById(1)); } ... } 运行测试用例: 第一次查询... [main] DEBUG - ==> Preparing: select id, nick, gender, age, city from t_member where id = ? sg :==> Preparing: select id, nick, gender, age, city from t_member where id = ? [main] DEBUG - ==> Parameters: 1(Integer)sg :==> Parameters: 1(Integer) [main] DEBUG - <== Total: 1sg :<== Total: 1 Member(id=1, nick=john, gender=男, age=20, city=北京) 第二次查询... Member(id=1, nick=john, gender=男, age=20, city=北京) 第三次查询... [main] DEBUG - ==> Preparing: select id, nick, gender, age, city from t_member where id = ? sg :==> Preparing: select id, nick, gender, age, city from t_member where id = ? [main] DEBUG - ==> Parameters: 1(Integer)sg :==> Parameters: 1(Integer) [main] DEBUG - <== Total: 1sg :<== Total: 1 Member(id=1, nick=john, gender=男, age=21, city=北京) 例程:Dynamic 在Mapper文件中: - select标签的useCache属性控制该查询是否使用缓存,默认为true - update标签的flushCache属性控制该更新是否清除缓存,默认为true