Mybatis(三)--Mybatis缓存配置

强烈推荐一个大神的人工智能的教程:http://www.captainai.net/zhanghan

前言

     使用缓存可以提高获取数据的速度,避免频繁的数据库交互,尤其是在查询越多,缓存命中率越高的情况下,使用缓存的作用就更加明显了。一般提到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一级缓存存在于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,则在后边所有缓存的配置都不起作用了。

   
      2.Mapper.xml中配置二级缓存

      在mapper中加一个cache标签即可。

     默认的二级缓存的效果:

     所有的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的二级缓存数据。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值