1.1二级缓存 1.1.1原理 mybatis和spring整合后一级缓存就没有了,sqlSession在不关闭的前提下2次查询就会从缓存中取,一级缓存缓存在sqlSession对象里面,当多用户查询的时候就用到二级缓存了。UserMapper缓存:会把根据id和根据name查询的用户信息写进缓存,如果有人发了insert语句则会把所有的用户信息清空,二级缓存是命名空间级别的。
二级缓存的范围是mapper级别(mapper同一个命名空间的缓存,在UserMapper.xml里面有一个命名空间<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">,不同的xml文件中命名空间可以相同),mapper以命名空间为单位创建缓存数据结构,结构是map<key、value>。 每次查询先看是否开启二级缓存,如果开启从二级缓存的数据结构中取缓存数据,
如果从二级缓存没有取到,再从一级缓存中找,如果一级缓存也没有,从数据库查询。 1.1.1mybatis二级缓存配置 在核心配置文件SqlMapConfig.xml中加入 <setting name="cacheEnabled" value="true"/>
描述 |
允许值 |
默认值 |
|
cacheEnabled |
对在此配置文件下的所有cache 进行全局性开/关设置。 |
true false |
true |
要在你的Mapper映射文件中添加一行: <cache /> ,表示此mapper开启二级缓存。 1.1.1查询结果映射的pojo序列化 mybatis二级缓存需要将查询结果映射的pojo实现 java.io.serializable接口,如果不实现则抛出异常: org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: cn.itcast.mybatis.po.User 因为二级缓存可以将内存的数据写到磁盘,存在对象的序列化和反序列化,所以要实现java.io.serializable接口。 如果结果映射的pojo中还包括了pojo,都要实现java.io.serializable接口。
1.1.1二级缓存禁用 对于变化频率较高的sql(比如支付宝银行账户余额),存到缓存没有意义因为一直在变化,需要禁用二级缓存: 在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。 <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false"> 1.1.2刷新缓存 如果sqlsession操作commit操作,对二级缓存进行刷新(全局清空)。 设置statement的flushCache是否刷新缓存,默认值是true,默认建议刷新,如果不刷新就会读取脏数据。把select中的 useCache="false"去掉,在insert或update中<update id="updateUser" parameterType="cn.itcast.mybatis.po.User" flushCache="false">加上flushCache="false" 1.1.3测试代码
//二级缓存的测试 @Test public void testCache2() throws Exception { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession(); UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class); //第一次查询用户id为1的用户,此时会写入缓存,如果设置刷新间隔为1秒,那么1秒以后缓存就清空了,下面的语句再查询的时候就会重新从数据库查询, User user = userMapper1.findUserById(1); System.out.println(user); sqlSession1.close(); //中间修改用户要清空缓存,目的防止查询出脏数据 /*user.setUsername("测试用户2"); userMapper3.updateUser(user); sqlSession3.commit(); sqlSession3.close();*/ //第二次查询用户id为1的用户 User user2 = userMapper2.findUserById(1); System.out.println(user2); sqlSession2.close();
1.1.1mybatis的cache参数(了解) mybatis的cache参数只适用于mybatis维护缓存。 flushInterval(刷新间隔,过了这个时间缓存就清空了)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 size(引用数目,缓存对象的个数)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。 readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。 eviction="FIFO" 表示缓存策略,比如到达时间后如何清空,清空的方案, 如下例子: <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> 这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU: 1.LRU – 最近最少使用的:移除最长时间不被使用的对象。 2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
时间: 2024-10-12 13:18:54