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

MyBatis学习笔记(九)缓存

程序员文章站 2022-07-13 16:14:35
...

 

在高并发的应用中,为提高访问速度,减少数据库的访问,可以使用缓存机制.

MyBatis缓存分为一级缓存和二级缓存

 

Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存

Mybatis二级缓存多个SqlSession共享的,其作用域是mapper同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。

一级缓存

一级缓存区域是根据SqlSession为单位划分的。

每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。

Mybatis内部存储缓存使用一个HashMapkeyhashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象。

sqlSession执行insertupdatedelete等操作commit提交后会清空缓存区域。

测试

 

//获取session
SqlSession session = sqlSessionFactory.openSession();
//获限mapper接口实例
UserDao dao = session.getMapper(UserDao.class);
//第一次查询
User user1 = dao.findUserById(1);
System.out.println(user1);
//第二次查询,由于是同一个session则不再向数据发出语句直接从缓存取出
User user2 = dao.findUserById(1);
System.out.println(user2);
//关闭session
session.close();

 从控制台的SQL信息可以看出,只发送了一次SQL语句。

 

 

 

//获取session
SqlSession session = sqlSessionFactory.openSession();
//获限mapper接口实例
UserDao dao = session.getMapper(UserDao.class);
//第一次查询
User user1 = dao.findUserById(1);
System.out.println(user1);
//在同一个session执行更新
User user_update = new User();
user_update.setId(1);
user_update.setUsername("李奎");
dao.updateUser(user_update);
session.commit();
//第二次查询,虽然是同一个session但是由于执行了更新操作session的缓存被清空,这里重新发出sql操作
User user2 = dao.findUserById(1);
System.out.println(user2);

 从控制台的SQL信息可以看出,发送了2次查询的SQL语句。

 

二级缓存

二级缓存区域是根据mappernamespace划分的,相同namespacemapper查询数据放在同一个区域,如果使用mapper代理方法每个mappernamespace都不同,此时可以理解为二级缓存区域是根据mapper划分。

每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。

Mybatis内部存储缓存使用一个HashMapkeyhashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

sqlSession执行insertupdatedelete等操作commit提交后会清空缓存区域

 

开启二级缓存

在核心配置文件mybatis-config.xml中加入:

<setting name="cacheEnabled" value="true"/>

 

描述

允许值

默认值

cacheEnabled

对在此配置文件下的所有cache 进行全局性开/关设置。

true false

true

 

要在你的Mapper映射文件中添加一行:  <cache /> ,表示此mapper开启二级缓存。

 

实现序列化

二级缓存需要查询结果映射的POJO对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。

      public class Orders implements Serializable

               public class User implements Serializable

 

测试

//获取session1
SqlSession session1 = sqlSessionFactory.openSession();
UserMapper userMapper = session1.getMapper(UserMapper.class);
//使用session1执行第一次查询
User user1 = userMapper.findUserById(1);
System.out.println(user1);
//关闭session1
session1.close();
//获取session2
SqlSession session2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = session2.getMapper(UserMapper.class);
//使用session2执行第二次查询,由于开启了二级缓存这里从缓存中获取数据不再向数据库发出sql
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
//关闭session2
session2.close();

 

禁用二级缓存

statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

刷新缓存

mapper的同一个namespace中,如果有其它insertupdatedelete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读

如下:

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

 Mybatis Cache参数

flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024

readOnly(只读)属性可以被设置为truefalse。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些但是安全,因此默认是false

 

如下例子:

<cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略, 默认的是 LRU:

<!--[if !supportLists]-->1.          <!--[endif]-->LRU  最近最少使用的:移除最长时间不被使用的对象。

<!--[if !supportLists]-->2.          <!--[endif]-->FIFO  先进先出:按对象进入缓存的顺序来移除它们。

<!--[if !supportLists]-->3.          <!--[endif]-->SOFT  软引用:移除基于垃圾回收器状态和软引用规则的对象。

<!--[if !supportLists]-->4.          <!--[endif]-->WEAK  弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

 

 

相关标签: 缓存 mybatis