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 准备数据表和数据



CREATE TABLE c_user( id INT PRIMARY KEY AUTO_INCREMENT,  NAME VARCHAR(20),  age INT);INSERT INTO c_user(NAME, age) VALUES('Tom', 12);INSERT INTO c_user(NAME, age) VALUES('Jack', 11);

2.3 创建表的实体类



public class CUser implements Serializable{ private int id; private String name; private int age;}

2.4 userMapper.xml



<select id="getUser" parameterType="int" resultType="CUser"> select * from c_user where id=#{id}</select><update id="updateUser" parameterType="CUser"> update c_user set name=#{name}, age=#{age} where id=#{id}</update>

2.5 测试



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



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

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



@Test public void testCacheOne2() { SqlSessionFactory factory = MybatisUtils.getFactory(); SqlSession session = factory.openSession(); String statement = "cn.imentors.mybatis.test9.userMapper.getUser"; CUser user = session.selectOne(statement, 1); System.out.println(user); //执行了session.clearCache(),清空缓存 session.clearCache(); user = session.selectOne(statement, 1); System.out.println(user); System.out.println("----------------"); session.close(); }

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



  



@Test public void testCacheOne3() { SqlSessionFactory factory = MybatisUtils.getFactory(); SqlSession session = factory.openSession(); String statement = "cn.imentors.mybatis.test9.userMapper.getUser"; CUser user = session.selectOne(statement, 1); System.out.println(user); //执行CUD操作 session.update("cn.imentors.mybatis.test9.userMapper.updateUser", new CUser(1, "Tom", 13)); session.commit(); user = session.selectOne(statement, 1); System.out.println(user); System.out.println("----------------"); session.close(); }

2.5.4 不同session



@Test public void testCacheOne4() { SqlSessionFactory factory = MybatisUtils.getFactory(); SqlSession session = factory.openSession(); String statement = "cn.imentors.mybatis.test9.userMapper.getUser"; CUser user = session.selectOne(statement, 1); System.out.println(user); //不是同一个Session对象 session.close(); session = factory.openSession(); user = session.selectOne(statement, 1); System.out.println(user); System.out.println("----------------"); session.close(); }

3 二级缓存



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


<mapper namespace="cn.imentors.mybatis.test9.userMapper"> <cache/>

  • 为什么在userMapper.xml添加呢,因为二级缓存是以namespace为单位,也就是说,二级缓存的作用域是实体SQL对应的xml,二级缓存是映射文件级的



3.2 测试


@Test public void testCacheTwo() { SqlSessionFactory factory = MybatisUtils.getFactory(); SqlSession session1 = factory.openSession(); SqlSession session2 = factory.openSession();  String statement = "cn.imentors.mybatis.test9.userMapper.getUser"; CUser user = session1.selectOne(statement, 1); session1.commit(); System.out.println(user);  user = session2.selectOne(statement, 1); session2.commit(); System.out.println(user); }

3.3 补充说明



1. 映射语句文件中的所有select语句将会被缓存。



2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。



3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。



4. 缓存会根据指定的时间间隔来刷新。



5. 缓存会存储1024个对象


<cache eviction="FIFO" //回收策略为先进先出flushInterval="60000" //自动刷新时间60ssize="512" //最多缓存512个引用对象readOnly="true"/> //只读