09_一级缓存与二级缓存

1 理解MyBatis缓存   

     正如大多数据持久层框架一样,MyBatis同样提供了一级缓存和二级缓存的支持。

1.1 一级缓存

        基于PerpetualCache的HashMap本地缓存,其存储作用域是Session,当Session flush或close之后,该Session中所有的Cache就将清空。

1.2 二级缓存

        二级缓存与一级缓存其机制是相同的,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用是Mapper(Namespace),并且可自定义存储源,如Ehcache

1.3 更新机制

        对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存 Namespaces)的进行了CUD操作后,默认该作用域下所有select中的缓存将被clear

2 一级缓存

2.1 需求

        根据id查询对应的用户记录对象

2.2 准备数据表和数据

  1. CREATE TABLE c_user(
  2. id INT PRIMARY KEY AUTO_INCREMENT,
  3. NAME VARCHAR(20),
  4. age INT
  5. );
  6. INSERT INTO c_user(NAME, age) VALUES('Tom', 12);
  7. INSERT INTO c_user(NAME, age) VALUES('Jack', 11);

2.3 创建表的实体类

  1. public class CUser implements Serializable{
  2. private int id;
  3. private String name;
  4. private int age;

2.4 userMapper.xml

  1. <select id="getUser" parameterType="int" resultType="CUser">
  2. select * from c_user where id=#{id}
  3. </select>
  4. <update id="updateUser" parameterType="CUser">
  5. update c_user set name=#{name}, age=#{age} where id=#{id}
  6. </update>
2.5 测试

2.5.1 默认情况下是开启一级缓存的

  1. @Test
  2. public void testCacheOne1() {
  3. SqlSessionFactory factory = MybatisUtils.getFactory();
  4. SqlSession session = factory.openSession();
  5. String statement = "cn.imentors.mybatis.test9.userMapper.getUser";
  6. CUser user = session.selectOne(statement, 1);
  7. System.out.println(user);
  8. //默认一级缓冲是开启的
  9. user = session.selectOne(statement, 1);
  10. System.out.println(user);
  11. System.out.println("----------------");
  12. session.close();
  13. }

2.5.2 通过执行session.clearCache()清空缓存

  1. @Test
  2. public void testCacheOne2() {
  3. SqlSessionFactory factory = MybatisUtils.getFactory();
  4. SqlSession session = factory.openSession();
  5. String statement = "cn.imentors.mybatis.test9.userMapper.getUser";
  6. CUser user = session.selectOne(statement, 1);
  7. System.out.println(user);
  8. //执行了session.clearCache(),清空缓存
  9. session.clearCache();
  10. user = session.selectOne(statement, 1);
  11. System.out.println(user);
  12. System.out.println("----------------");
  13. session.close();
  14. }

2.5.3 通过执行CUD操作,清空一级缓存

  
  1. @Test
  2. public void testCacheOne3() {
  3. SqlSessionFactory factory = MybatisUtils.getFactory();
  4. SqlSession session = factory.openSession();
  5. String statement = "cn.imentors.mybatis.test9.userMapper.getUser";
  6. CUser user = session.selectOne(statement, 1);
  7. System.out.println(user);
  8. //执行CUD操作
  9. session.update("cn.imentors.mybatis.test9.userMapper.updateUser", new CUser(1, "Tom", 13));
  10. session.commit();
  11. user = session.selectOne(statement, 1);
  12. System.out.println(user);
  13. System.out.println("----------------");
  14. session.close();
  15. }

2.5.4 不同session

  1. @Test
  2. public void testCacheOne4() {
  3. SqlSessionFactory factory = MybatisUtils.getFactory();
  4. SqlSession session = factory.openSession();
  5. String statement = "cn.imentors.mybatis.test9.userMapper.getUser";
  6. CUser user = session.selectOne(statement, 1);
  7. System.out.println(user);
  8. //不是同一个Session对象
  9. session.close();
  10. session = factory.openSession();
  11. user = session.selectOne(statement, 1);
  12. System.out.println(user);
  13. System.out.println("----------------");
  14. session.close();
  15. }

3 二级缓存

3.1 开启MyBatis的二级缓存,即在userMapper.xml,添加如下代码

  1. <mapper namespace="cn.imentors.mybatis.test9.userMapper">
  2. <cache/>
  • 为什么在userMapper.xml添加呢,因为二级缓存是以namespace为单位,也就是说,二级缓存的作用域是实体SQL对应的xml,二级缓存是映射文件级的

3.2 测试

  1. @Test
  2. public void testCacheTwo() {
  3. SqlSessionFactory factory = MybatisUtils.getFactory();
  4. SqlSession session1 = factory.openSession();
  5. SqlSession session2 = factory.openSession();
  6. String statement = "cn.imentors.mybatis.test9.userMapper.getUser";
  7. CUser user = session1.selectOne(statement, 1);
  8. session1.commit();
  9. System.out.println(user);
  10. user = session2.selectOne(statement, 1);
  11. session2.commit();
  12. System.out.println(user);
  13. }

3.3 补充说明

1. 映射语句文件中的所有select语句将会被缓存。
2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。
3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
4. 缓存会根据指定的时间间隔来刷新。
5. 缓存会存储1024个对象
  1. <cache
  2. eviction="FIFO" //回收策略为先进先出
  3. flushInterval="60000" //自动刷新时间60s
  4. size="512" //最多缓存512个引用对象
  5. readOnly="true"/> //只读
捐赠我们
    良师益友工作室一直在致力于帮助编程爱好更加快速方便地学习编程,如果您对我们的成果表示认同并且觉得对你有所帮助,欢迎您对我们捐赠^_^。
    









   

原文地址:https://www.cnblogs.com/imentors/p/4813294.html