Fork me on GitHub

Mybatis缓存配置—— 一级缓存

一级缓存又叫做本地缓存,在程序启动的时候就会正常启动,一般不加以设置的话就是默认启动一级缓存模式,先看一下一级缓存到底是如何起到作用的。

1. 正在com.example.simple下新建CacheTest类,代码如下:

package com.example.simple.mapper;

import com.example.simple.model.SysUser;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;


public class CacheTest extends BaseMapperTest {
        @Test
        public void testL1Cache(){
            SqlSession sqlSession = getSqlSession();
            SysUser user = null;
            try{
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                user = userMapper.selectById(1l);
                System.out.println("第二次查询————");
                user.setUserName("new name");
                SysUser user1 = userMapper.selectById(1l);
                Assert.assertEquals(user1.getUserName(),"new name");
                Assert.assertEquals(user,user1);

            }finally {
                sqlSession.close();

            }
            System.out.println("开启新的sqlSession");
            sqlSession = getSqlSession();
            try{
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                SysUser user1 = userMapper.selectById(1l);
                Assert.assertNotEquals("new name" , user1.getUserName());
                Assert.assertNotEquals(user1,user);
                userMapper.deleteById(2l);
                SysUser user2 = userMapper.selectById(1l);
                Assert.assertNotEquals(user1,user2);

            }finally {
                sqlSession.close();
            }

        }

}

测试结果如下:

DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1
第二次查询————
开启新的sqlSession
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: delete from mybatis.sys_user u where u.id = ?
DEBUG [main] - ==> Parameters: 2(Long)
DEBUG [main] - <== Updates: 0
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1

解析:从测试结果可以看出,

  开启的第一个sqlSession中,数据库查询执行完第一个selectById后就没再执行下一个selectById了,而且Assert.assertEquals(user,user1);也并没有出现异常,说明user和user1此时判断出二者是同一实例,即使user和user1两者的username并不一样,这就是mybatis一级缓存在捣鬼了。MyBatis一级缓存存在于 SqlSession 的生命周期中,在同一SqlSession 中查询时, MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象。这样一来,就出现了两次selectById函数执行却执行了一次的情况的原因就能得到合理的解释。

  开启的第二个sqlSession中,两次selectById函数都得到了执行,而且user1和user2这次执行出来并不是同一实例,这又是为什么呢?这段代码和上一段代码的差异在于这段代码在中间执行了一个 deleteById 操作 ,然后使用相同的方法和参数获取了 user2 实例,从日志和结果来看, user2和user1 也是完全不同的两个对象。这是因为任何的 INSERT、UPDATE、DELETE 操作都会清空一级缓存,所以查询 user2 的时候由于缓存不存在,就会再一次执行数据库查询获取数据。这时二者自然就不会是同一个实例了。

改进:在使用 MyBatis的过程中,要避免在使用如上代码中的 user1 时出现的错误。我们可能以为获取的 user1 应该是数据库中的数据,却不知道 user的一个重新赋值会影响到 user2,如果不想让 selectByid 方法使用一级缓存 ,可以对该方法做如下修改。

<select id="selectById" flushCache="true" resultMap="userMap">
        select * from sys_user where id = #{id}
    </select>

这时执行情况如下:(注释掉如下代码执行)

//Assert.assertEquals(user1.getUserName(),"new name");
//Assert.assertEquals(user,user1);

DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1
第二次查询————
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1
开启新的sqlSession
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: delete from mybatis.sys_user u where u.id = ?
DEBUG [main] - ==> Parameters: 2(Long)
DEBUG [main] - <== Updates: 0
DEBUG [main] - ==> Preparing: select * from sys_user where id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, test@com.example, <<BLOB>>, <<BLOB>>, 2020-12-01 20:02:01
DEBUG [main] - <== Total: 1

一级缓存成功被清空。

posted @ 2020-12-28 16:36  叶语婷  阅读(358)  评论(0编辑  收藏  举报