当前位置: 首页 >服务端 > MyBatis Cache

MyBatis Cache

一、一级缓存

/** * 一级缓存(本地缓存):SqlSession 级别。一级缓存是默认开启的,为 SqlSession 级别的一个Map * 与数据库同一次会话期间查询到的数据会放在本地缓存中,以后如果需要获取相同的数据,直接从缓存中获取。 */public static void main(String[] args) throws IOException {SqlSession session = null;try {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);session = sqlSessionFactory.openSession();MyUserMapper mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));System.out.println(mapper.selectMyUserById(7));} finally {session.close();}}

MyBatis Cache _ JavaClub全栈架构师技术笔记

一级缓存失效的几种情况,相同的查询也会向数据库发送SQL

public static void main(String[] args) throws IOException {SqlSession session = null;try {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);session = sqlSessionFactory.openSession();MyUserMapper mapper = session.getMapper(MyUserMapper.class);// sqlSession 不同System.out.println(mapper.selectMyUserById(7));session = sqlSessionFactory.openSession();mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));// sqlSession 相同,查询条件不同(当前一级缓存中还没有这个数据)System.out.println(mapper.selectMyUserById(7));System.out.println(mapper.selectMyUserById(8));// sqlSession 相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)System.out.println(mapper.selectMyUserById(7));mapper.updateMyUser(new MyUser(10,"xasx",24,null));System.out.println(mapper.selectMyUserById(7));// sqlSession 相同,手动清除了一级缓存System.out.println(mapper.selectMyUserById(7));session.clearCache();System.out.println(mapper.selectMyUserById(7));} finally {session.close();}}

MyBatis Cache _ JavaClub全栈架构师技术笔记

 

二、二级缓存

1.开启二级缓存 mybatis-config.xml

<settings><!-- 开启全局二级缓存 --><setting name="cacheEnabled" value="true"/><!-- 自动映射有三种模式,NONE、PARTIAL、FULL。NONE 不启用自动映射,PARTIAL 只对非嵌套的 resultMap 进行自动映射,FULL 表示对所有的 resultMap 都进行自动映射。默认为 PARTIAL --><setting name="autoMappingBehavior" value="PARTIAL"/><!-- 数据库字段下划线转Bean字段的驼峰命名 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 控制台打印SQL --><setting name="logImpl" value="STDOUT_LOGGING" /><!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认false --><setting name="lazyLoadingEnabled" value="true"/><!-- 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。默认false (true in ≤3.4.1) --><setting name="aggressiveLazyLoading" value="false"/></settings>

2.配置二级缓存 xxxMapper.xml

<!-- namespace 对应接口文件的全路径 --><mapper namespace="com.dao.MyUserMapper"><cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache><!-- eviction:缓存的回收策略:默认的是 LRU• LRU – 最近最少使用的:移除最长时间不被使用的对象。• FIFO – 先进先出:按对象进入缓存的顺序来移除它们。• SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。• WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。flushInterval:缓存刷新间隔,缓存多长时间清空一次,默认不清空,设置一个毫秒值readOnly:缓存中的数据是否只读true:只读,会将数据在缓存中的引用交给用户。数据可能被修改,不安全,速度快false:非只读,会利用序列化和反序列的技术克隆一份新的数据返回。安全,速度慢size:缓存存放多少元素type:指定自定义缓存的全类名,实现 org.apache.ibatis.cache.Cache 接口 --><select id="selectMyUserById" resultType="myUser">  select * from myuser where id = #{id}</select>

3.实体类实现序列化接口 Serializable

public class MyUser implements Serializable {private Integer id;private String name;private Integer age;private Dept dept;

4.测试

/** * 二级缓存(全局缓存):基于 namespace 级别的缓存,一个 namespace 对应一个二级缓存(map) *  * 创建会话:查询一条数据,这个数据就会被放在当前会话的一级缓存中 * 会话关闭:一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,会先找二级缓存中的内容,没有就找一级缓存,再没有就会发送 SQL 查询数据库 * 效果:数据会从二级缓存中获取,查出的数据都会被默认先放在一级缓存中。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中 * 使用: *  1)、在全局配置中开启二级缓存:<setting name="cacheEnabled" value="true"/> * 2)、在 xxxMapper.xml 中配置二级缓存:<cache/> * 3)、POJO 实现序列化接口 Serializable */public static void main(String[] args) throws IOException {SqlSession session = null;try {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);session = sqlSessionFactory.openSession();MyUserMapper mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));// 关闭 session 让一级缓存中类容提交到二级缓存session.close();// 重新获取 sqlSessionsession = sqlSessionFactory.openSession();mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));} finally {session.close();}}

MyBatis Cache _ JavaClub全栈架构师技术笔记

 

三、缓存相关配置

代码配置

// 只清除当前 session 的一级缓存session.clearCache();

全局设置

<settings><!-- 二级缓存设置,不影响一级缓存 --><setting name="cacheEnabled" value="false"/><!-- 本地(一级)缓存作用域,默认 SESSION,会缓存一个会话(SqlSession)中执行的所有查询。 设置为 STATEMENT,会话仅作用在语句执行上,对 SqlSession 的调用将不会共享数据,可认为是禁用一级缓存 --><setting name="localCacheScope" value="SESSION"/></settings>

SQL 映射文件配置

<!-- flushCache:将其设置为 true,任何时候只要 SQL 被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句),false(对应查询语句)。 useCache:将其设置为 true,将会导致本条 SQL 的结果被二级缓存(不影响一级),默认值:对 select 元素为 true --><select id="selectMyUserById" resultType="myUser" useCache="true" flushCache="false">  select * from myuser where id = #{id}</select>

也可以在接口上配置

@Options(flushCache = Options.FlushCachePolicy.FALSE, useCache = true)public MyUser selectMyUserById(Integer id);

 

四,使用第三方缓存(二级)

以 ehcache 为例

1.导入依赖

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>mybatis</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency><dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.7.0</version></dependency><dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.1.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-nop</artifactId><version>1.7.26</version></dependency></dependencies><build><plugins><!-- 指定jdk --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build></project>

2.添加缓存配置文件 ehcache.xml

<?xml version="1.0" encoding="UTF-8"?><ehcache><!-- 磁盘保存路径 --><diskStore path="D:\ehcache" /><!--diskStore:指定数据在磁盘中的存储位置。defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略以下是必须属性:maxElementsInMemory - 在内存中缓存的element的最大数目maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大eteal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上以下是可选属性:timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大diskSpoolBufferSizeMB - 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)--><defaultCachemaxElementsInMemory="10000"maxElementsOnDisk="10000000"eteal="false"overflowToDisk="true"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache></ehcache>

3.修改缓存配置,xxxMapper.xml

<!-- namespace 对应接口文件的全路径 --><mapper namespace="com.dao.MyUserMapper"><!-- 引用缓存:namespace:指定和哪个名称空间下的缓存一样 --><!--<cache-ref namespace="com.dao.Dept"/>--><!--使用自定义缓存--><cache type="org.mybatis.caches.ehcache.EhcacheCache"/><select id="selectMyUserById" resultType="myUser" useCache="true" flushCache="false">  select * from myuser where id = #{id}</select>

5.测试

/** * 使用第三方缓存: *1)、导入依赖; *2)、xxxMapper.xml 中使用自定义缓存 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> */public static void main(String[] args) throws IOException {SqlSession session = null;try {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);session = sqlSessionFactory.openSession();MyUserMapper mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));session.close();session = sqlSessionFactory.openSession();mapper = session.getMapper(MyUserMapper.class);System.out.println(mapper.selectMyUserById(7));} finally {if (session != null) {session.close();}}}

MyBatis Cache _ JavaClub全栈架构师技术笔记


http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache

http://www.mybatis.org/ehcache-cache/index.html

作者:江湖小小白
来源链接:https://www.cnblogs.com/jhxxb/p/10495953.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/server/112468.html

标签:Cache
分享给朋友: