欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mybatis(三)--Mybatis缓存配置

程序员文章站 2022-05-29 12:58:36
...

前言

     使用缓存可以提高获取数据的速度,避免频繁的数据库交互,尤其是在查询越多,缓存命中率越高的情况下,使用缓存的作用就更加明显了。一般提到Mybatis缓存的时候都是指二级缓存,一级缓存默认会启用。

一级缓存

     1.先写一个基本的mapper来创建sqlsession,类名为BaseMapperTest
public class BaseMapperTest
{
    private static SqlSessionFactory sqlSessionFactory;
    @BeforeClass
    public static void init(){
        try{
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            reader.close();
        }catch (IOException ignore){
            ignore.printStackTrace();
        }
    }

    public SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}
     2.创建一个缓存的测试类,CacheTest
public class CacheTest extends BaseMapperTest {
    @Test
    public void testL1Cache(){
        //获取SqlSession
        SqlSession sqlSession = getSqlSession();
        SysUser user1 = null;
        try {
            //获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //调用selectById方法
            user1 = userMapper.selectById(1L);
            //对当前获取的对象重新赋值
            user1.setUserName("New Name");
            //再次查询获取id相同的用户
            SysUser user2 = userMapper.selectById(1L);
            //虽然没有更新数据库,但是user1和user2的名字相同
            Assert.assertEquals("New Name",user2.getUserName());
            //无论如何user1和user2是同一个实例
            Assert.assertEquals(user1,user2);
        }finally {
            sqlSession.close();
        }
        System.out.println("开启新的SqlSession");
        //开启一个新的sqlsession
        sqlSession = getSqlSession();
        try {
            //获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser user2 = userMapper.selectById(1L);
            Assert.assertNotEquals("New Name",user2.getUserName());
            //这里的user2和前一个session查询的结果是两个不同的实例
            Assert.assertNotEquals(user1,user2);
            //执行删除操作
            userMapper.deleteById(2L);
            //获取user3
            SysUser user3 = userMapper.selectById(1L);
            //这里的user2和user3是两个不同的实例
            Assert.assertNotEquals(user2,user3);
        }finally {
            sqlSession.close();
        }
    }
}
      运行结果如下,在第一个try语句块中,我们写了两次查询数据库的语句,但是打印出的sql只有一条,证明第二条没有查询数据库,而是查询了缓存,并且user1和user2是同一个实例,先从数据库中获取user1的值,user1重新对userName赋值,第二次查询user2发现user2的userName是user1修改后的值。
     Mybatis(三)--Mybatis缓存配置
     Mybatis一级缓存存在于SqlSession的生命周期中,在同一个SqlSession中查询时,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果放到一个Map中,如果同一个SqlSession中执行的方法和参数完全一致,那么通过算法生成相同的键值,当Map缓存对象中已经 存在该键值时,则会返回缓存中的对象.
    如果不想使用缓存怎么办呢?可以在Mapper的方法上添加一个flushCache="true"的配置,他会在执行查询之前将缓存清除。
 <select id="selectById" flushCache="true" resultMap="userMap">
        SELECT * FROM sys_user WHERE id=#{id}
 </select>
    第二个try语句块中我们重新获取了一个新的sqlsession,查询结果显示,user2和第一个语句块中的user1没有任何关系,当我们执行删除操作后,用同一个sqlsession执行相同的查询,结果赋值给user3,结果表示user2和user3是不同的实例,原因是因为所有的insert,update,delete操作都会清空一级缓存。

二级缓存

     Mybatis的二级缓存不同于一级缓存,一级缓存存在于sqlsession的生命周期中,而二级缓存可以理解为存在sqlsessionFactory的生命周期中。
     1.Mybatis配置文件的简单配置
     在Mybatis的全局配置settings中有一个参数cacheEnabled,这个参数是二级缓存的全局开关.默认为true,所以可以不配置,如果将其设置为false,则在后边所有缓存的配置都不起作用了。
   Mybatis(三)--Mybatis缓存配置
      2.Mapper.xml中配置二级缓存
      在mapper中加一个cache标签即可。
Mybatis(三)--Mybatis缓存配置
     默认的二级缓存的效果:
     所有的Select语句将会被缓存
     映射语句中所有的insert,update,delete操作会刷新缓存
     缓存会使用LRU算法来回收
     缓存会存储集合或对象的1024个引用
     缓存会被视为read/write的
<cache
    eviction="FIFO"
    flushInterval="60000"
    size="512"
    readOnly="true"/>
    3.Mapper接口中配置二级缓存
    在接口上加上@CacheNamespace属性,如果在接口和XML同时配置了缓存,则需要用到参照缓存,否则会报错,写法是在接口上写@CacheNamespaceRef(XXXMapper.Class)

总结

    Mybatis默认提供的缓存是基于map实现的内存缓存,可以满足基本使用,当数据量大的时候可以借助一些缓存框架或Redis缓存来协助保存Mybatis的二级缓存数据。