一级缓存
一级缓存是Sqlsession级别的缓存,再操作数据库时需要构造sqlsession对象,在对象中有一个内存区域 数据结构 hashMap 用于存储缓存数据。不同的sqlsession之间的缓存数据区域 hashmap互不影响。
mybatis默认开启一级缓存
一级缓存的作用域是同一个sqlsession,在同一个sqlsession中两次执行相同的sql语句,第一次执行完毕会将查询出的数据写到缓存中,第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率,当一个sqlsession结束后该sqlsession中的一级缓存也就不存在了。
public void testCache1() throws Exception{
SqlSessionsqlSession = sqlSessionFactory.openSession();//创建代理对象
UserMapperuserMapper = sqlSession.getMapper(UserMapper.class);
//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
Useruser1 = userMapper.findUserById(1);
System.out.println(user1);
// 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
//更新user1的信息
user1.setUsername("测试用户22");
userMapper.updateUser(user1);
//执行commit操作去清空缓存
sqlSession.commit();
//第二次发起请求,查询id为1的用户
Useruser2 = userMapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
如果不commit的错误流程为:
开始执行时,开启事务,创建SqlSession对象
第一次调用mapper的方法findUserById(1)
更新数据
第二次调用mapper的方法findUserById(1),从一级缓存中取数据
aop控制 只要方法结束,sqlSession关闭 sqlsession关闭后就销毁数据结构,清空缓存
Service结束sqlsession关闭
因为上面有commit操作,所以正确流程
开始执行时,开启事务,创建SqlSession对象
第一次调用mapper的方法findUserById(1)
更新数据
清空commit
第二次调用mapper的方法findUserById(1),从一级缓存中无数据,从数据库中取数据
aop控制 只要方法结束,sqlSession关闭 sqlsession关闭后就销毁数据结构,清空缓存
Service结束sqlsession关闭
只要是在同一个sqlsession中,一级缓存才会生效,如果sqlsession.commit() 或者 sqlsession.close()就会清空sqlsession,一级缓存也随之消失。
二级缓存
二级缓存是mapper级别的缓存,多个sqlsession去操作同一个mapper的sql语句,多个sqlsession去操作数据库得到数据会存在二级缓存区域,多个slqsession可以共同二级缓存,二级缓存是多个sqlsession共享的。
Usermapper有一个二级缓存区域 按照namespace分,如果namespace相同则使用同一个相同的二级缓存区,其它mapper也有自己依照namespace区分的二级缓存区域。也就是说拥有相同的namespace的Usermapper共享一个二级缓存
开启缓存
sqlMapConfig中
<setting name="cacheEnabled"value="true"/>
<!-- 全局配置参数,需要时再设置 -->
<settings>
<!-- 开启二级缓存 默认值为true -->
<setting name="cacheEnabled" value="true"/>
</settings>
在Usermapper.xml中开启二级缓存,UserMapper.xml下的执行完成会存储到它的缓存区域hashMap
下面是开启redis缓存
<mapper namespace="cn.mybatis.xml.mapper.UserMapper">
<!-- redis配置项 -->
<cache type="org.mybatis.caches.redis.RedisCache" />
...
redis与mybatis的整合:https://blog.csdn.net/magi1201/article/details/85635878
如何使用二级缓存
public class Userimplements Serializable {
//Serializable实现序列化,为了将来反序列化
// 二级缓存测试
@Test
public void testCache2() throws Exception {
SqlSessionsqlSession1 = sqlSessionFactory.openSession();
SqlSessionsqlSession2 = sqlSessionFactory.openSession();
SqlSessionsqlSession3 = sqlSessionFactory.openSession();
// 创建代理对象
UserMapperuserMapper1 = sqlSession1.getMapper(UserMapper.class);
// 第一次发起请求,查询id为1的用户
Useruser1 = userMapper1.findUserById(1);
System.out.println(user1);
//这里执行关闭操作,将sqlsession中的数据写到二级缓存区域
sqlSession1.close();
//使用sqlSession3执行commit()操作
UserMapperuserMapper3 = sqlSession3.getMapper(UserMapper.class);
Useruser = userMapper3.findUserById(1);
user.setUsername("张明明");
userMapper3.updateUser(user);
//执行提交,清空UserMapper下边的二级缓存
sqlSession3.commit();
sqlSession3.close();
UserMapperuserMapper2 = sqlSession2.getMapper(UserMapper.class);
// 第二次发起请求,查询id为1的用户
Useruser2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}
执行结果:
sqlsession1中使用findUserById(1)
关闭sqlsession1
sqlsession3中使用findUserById(1),从缓存中取出数据
sqlSession3.commit();
sqlSession3.close()
sqlSession2中使用findUserById(1)无法拿到数据(commit刷新二级缓存)
sqlSession2.close()
原文地址:https://blog.csdn.net/qq_35688140/article/details/89848539