当前位置:首页 » 文件管理 » mybatis缓存ehcache

mybatis缓存ehcache

发布时间: 2023-02-12 06:58:55

‘壹’ mybatis的缓存机制是怎么样的

MyBatis 同样提供了一级缓存和二级缓存的支持
一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

‘贰’ mybatis二级缓存原理

mybatis篇

一级缓存的作用域是sqlsession级别的,也就是说不同的Sqlsession是不会走一级缓存的,那么如果需要跨Sqlsession的缓存,就需要使用到二级缓存了。

二级缓存的话默认是关闭的,所以需要我们开启,开启的方式官网也有介绍,需要在mybatis-config.xml核心配置文件中开启二级缓存功能,并且我们mapper.xml中也需要加入<cache/>标签,二者缺一不可,后面我们看源码就能知道为啥这两个缺一不可。

先来看个例子

执行结果很意外,为什么二级缓存的功能都开启了,结果sql还是执行了2次,并没有走缓存,其实,二级缓存还有一个要注意的点那就是必须要提交事务二级缓存才会保存记录,因为已经是跨SqlSession共享缓存了,所以事务必须要提交,否则会读取到因混滚导致的错误数据。

有个地方需要注意,二级缓存的Sqlsession中的Executor实际上是CachingExecutor

我们知道getMapper最终的执行都会走到MapperProxy类中的invoker方法,具体就来分析这个类。

最后来到了重点的地方

CacheKey我们可以认为他就是每个方法对应的一个唯一标识符。

这里我们就可以看出为什么之前两者必须要配置,cacheEnable开启了才会用CachingExecutor包装一下BaseExecutor,而<cache/>标签只有配置了才会走缓存的逻辑

这里的tcm

到这,我们就差不多揭开了二级缓存的秘密,重要的还是<cache/>这个标签,因为它的存在就对应着每个mapper.xml中的一个具体Cache类,而这个类在每个mapper.xml中又是同一个,所以最终的值是放入了Cache类中,key为CacheKey,value就是sql执行的结果。
至于为什么需要事务提交才能命中二级缓存,我们看下put方法就知道

这里的putObject并没有真正的把值存入Cache中,而是存入了待提交的Map中,所以再来看下commit做了什么

具体看tcm.commit()

而这里可以看到此处会遍历所有的TransactionCache并执行commit方法

真相就出来了,会遍历待提交的Map然后把里面的值都存入Cache中,所以后面的查询就能直接从Cache中拿到值了。

总结
二级缓存先会把Sqlsession中的Executor包装成包装成CacheingExecutor,所有的sql都会经过这个类,而该类通过mapper.xml中配置的唯一<cache/>标签生成的Cache类存放每个方法执行的结果

‘叁’ MyBatis二级缓存带来的问题

MyBatis二级缓存使用的在某些场景下会出问题,来看一下为什么这么说。

假设我有一条select语句(开启了二级缓存):

selecta.col1, a.col2, a.col3, b.col1, b.col2, b.col3fromtableA a, tableB bwherea.id= b.id;

对于tableA与tableB的操作定义在两个Mapper中,分别叫做MapperA与MapperB,即它们属于两个命名空间,如果此时启用缓存:

MapperA中执行上述sql语句查询这6个字段

tableB更新了col1与col2两个字段

MapperA再次执行上述sql语句查询这6个字段(前提是没有执行过任何insert、delete、update操作)

此时问题就来了,即使第(2)步tableB更新了col1与col2两个字段,第(3)步MapperA走二级缓存查询到的这6个字段依然是原来的这6个字段的值,因为我们从CacheKey的3组条件来看:

<select>标签所在的Mapper的Namespace+<select>标签的id属性

RowBounds的offset和limit属性,RowBounds是MyBatis用于处理分页的一个类,offset默认为0,limit默认为Integer.MAX_VALUE

<select>标签中定义的sql语句

对于MapperA来说,其中的任何一个条件都没有变化,自然会将原结果返回。

这个问题对于MyBatis的二级缓存来说是一个无解的问题,因此使用MyBatis二级缓存有一个前提: 必须保证所有的增删改查都在同一个命名空间下才行 。

‘肆’ java软件工程师主要学习哪些课程

第一阶段,Java SE基础:

Java环境搭建、Java流程控制语句-for循环、switch选择判断、循环嵌套、数组拷贝、多维数组、final关键字、构造函数的调用、类的访问权限和路径、面向对象高级特性、Java异常处理、Set,Map,List接口及接口实现类、Java线程、同步阻塞、JavaIO流、文件的操作,复制,读写,删除等。

第二阶段,JavaWeb:

MySQL安装、管理、创建数据库、MySQL
UPDATE 查询、Mysql高级操作、JDBC、JDBC数据库连接操作,JDBC动态Sql处理、Servlet3.0
网页重定向、Servlet3.0 新增的注解支持、AJAX、responseText属性详解等。

第三阶段,Java高级框架-SSH:

Struts2异常处理、Struts2+Log4j集成、Struts2和JSON实例、Hibernate5、Hibernate集合映射、Hibernate组件映射、Spring4.0、SpringAOP
+ AspectJ框架、Spring 与其它Web框架集成、Spring Hibernate支持等。

第四阶段,Java高级框架-SSM:

SpringMVC、Spring MVC生成JSON数据、MyBatis、MyBatis 环境配置及入门、Mybatis set标签、Mybatis trim标签、Shiro、Shiro快速入门教程、Shiro Web应用等。

第五阶段,SpringBoot+VUE全栈框架:

SpringBoot、全局异常处理、过滤器监听器、EHCache缓存、SpringBoot Quartz定时任务、Vue、Vue.js 安装、模板语法、计算属性、事件处理器、Vue.js 自定义指令、Vue.js 路由等

第六阶段,特色课程:

ActiveM环境搭建、生产者和消费者、消息持久化操作、RSA数字加密算法、Codebar条形码生成器、zxing二维码生成器、HighCharts统计图、Echarts统计图、网络播放器ckplayer、嵌入式网络播放器,可以浏览器和移动端随意使用

第七阶段,互联网框架的高级应用1:

分布式服务框架的理解,Dubbo架构设计详解及其核心要点,框架运行原理分析、SpringData数据访问、Lucene搜索引擎、Lucene的全文搜索服务器介绍、索引建立方式、Solr海量数据搜索引擎、Socket网络通信、实现RMI远程对象通讯、使用JMS消息服务、Kafka分布式消息系统、WebService与Restful
WS等

第八阶段,互联网框架的高级应用2:

Spring Security安全框架、实现Web应用安全控制、缓存应用与EhCache框架、OSCache与JBossCache框架、MyBatis与Hibernate缓存机制、NoSQL应用与SQL调优、MongoDB
NoSQL数据库、Redis内存数据库、实现Redis

Session共享、SQL语句的优化、实现数据库读写分离、WEB应用集群及性能优化、Maven项目管理工具、Web服务器负载均衡、实现Nginx与Tomcat集群、使用LoadRunner测试工具、性能优化之内存调优、代码优化与重构的方法等。

对java有兴趣的小伙伴们,不妨先从java入门开始!B站上有很多的java教学视频,从基础到高级的都有,还挺不错的,知识点讲的很细致,还有完整版的学习路线图。也可以自己去看看,下载学习试试。

‘伍’ Spring+mybatis整合ehcache无异常,输出这样的日志算是缓存生效了吗

把持久层的log打开,看有没有sql输出就知道了,再简单的方法把数据库的query log打开,看

‘陆’ mybatis的缓存有几种

1、一级缓存

MyBatis默认开启了一级缓存,一级缓存是在SqlSession 层面进行缓存的。即,同一个SqlSession ,多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。

但是不同的SqlSession对象,因为不用的SqlSession都是相互隔离的,所以相同的Mapper、参数和方法,他还是会再次发送到SQL到数据库去执行,返回结果。

2、二级缓存

为了克服这个问题,需要开启二级缓存,是的缓存zaiSqlSessionFactory层面给各个SqlSession 对象共享。默认二级缓存是不开启的,需要手动进行配置。

<cache/>

如果这样配置的话,很多其他的配置就会被默认进行,如:

  • 映射文件所有的select 语句会被缓存

  • 映射文件的所有的insert、update和delete语句会刷新缓存

  • 缓存会使用默认的Least Recently Used(LRU,最近最少使用原则)的算法来回收缓存空间

  • 根据时间表,比如No Flush Interval,(CNFI,没有刷新间隔),缓存不会以任何时间顺序来刷新

  • 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用

  • 缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以很安全的被调用者修改,不干扰其他调用者或县城所作的潜在修改

  • 可以在开启二级缓存时候,手动配置一些属性

  • <cache eviction="LRU" flushInterval="100000" size="1024" readOnly="true"/>

  • 各个属性意义如下:

  • eviction:缓存回收策略
    - LRU:最少使用原则,移除最长时间不使用的对象
    - FIFO:先进先出原则,按照对象进入缓存顺序进行回收
    - SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
    - WEAK:弱引用,更积极的移除移除基于垃圾回收器状态和弱引用规则的对象

  • flushInterval:刷新时间间隔,单位为毫秒,这里配置的100毫秒。如果不配置,那么只有在进行数据库修改操作才会被动刷新缓存区

  • size:引用额数目,代表缓存最多可以存储的对象个数

  • readOnly:是否只读,如果为true,则所有相同的sql语句返回的是同一个对象(有助于提高性能,但并发操作同一条数据时,可能不安全),如果设置为false,则相同的sql,后面访问的是cache的clone副本。

  • 可以在Mapper的具体方法下设置对二级缓存的访问意愿:

  • useCache配置

    如果一条语句每次都需要最新的数据,就意味着每次都需要从数据库中查询数据,可以把这个属性设置为false,如:

  • <select id="selectAll" resultMap="BaseResultMap" useCache="false">

  • 刷新缓存(就是清空缓存)

    二级缓存默认会在insert、update、delete操作后刷新缓存,可以手动配置不更新缓存,如下:

  • <update id="updateById" parameterType="User" flushCache="false" />


  • 3、自定义缓存

    自定义缓存对象,该对象必须实现 org.apache.ibatis.cache.Cache 接口

每次查询数据库前,MyBatis都会先在缓存中查找是否有该缓存对象。只有当调用了commit() 方法,MyBatis才会往缓存中写入数据,数据记录的键为数字编号+Mapper名+方法名+SQL语句+参数格式,值为返回的对象值。

‘柒’ mybatis ehcache 为什么总是缓存不到

通过对力敏感的传感器,感受手机在变换姿势时,重心的变化,使手机光标变化位置从而实

现选择的功能。手机重力感应技术:利用压电效应实现,简单来说是是测量内部一片重物(重

物和压电片做成一体)重力正交两个方向的分力大小,来判定水平方向。

‘捌’ Spring+mybatis整合ehcache无异常,输出这样的日志算是缓存生效了吗

Service 代码: @Service public class GameareaServiceImpl extends BaseServiceImpl implements IGameareaService{ @Resource private GameareaMapper gameareaMapper; @Override @Cacheable(value="myCache") public Gamearea find(int id) {。

‘玖’ Mybatis的缓存讲解

前段时间阿粉的一个朋友和阿粉吃饭,在吃饭的时候和阿粉疯狂的吐槽面试官,说面试官问的问题都是些什么问题呀,我一个干了三四年的开发,也不说问点靠谱的,阿粉很好奇,问题问完基础的,一般不都是根据你自己的简历进行提问么?而接下来他说的出来的问题,阿粉表示,阿粉需要继续学习了。

说到这个,读者大人们肯定心想,阿粉是在开玩笑么?你一个 Java 程序员,你不知道Mybatis是啥么?不就是个持久层的框架么,这东西有啥好说的呢?但是阿粉还是要给大家说。

为什么说 Mybatis 是一个半自动 ORM 的框架呢?

ORM,是Object和Relation之间的映射,而Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 框架,而Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。

这也是为什么有些面试官在面试初级程序员的时候,很喜欢说,你觉得 Mybatis , 和 Hibernate 都有什么优缺点,为啥你们选择使用的 Mybatis 而不选择使用 Hibernate 呢?

我们都说了 Mybatis是什么了,接下来肯定需要说说面试官都问了什么问题,能让阿粉的朋友变得非常犹豫。

当我们面试的时候,说完这个,一般情况下,面试官一定会追问下去,毕竟技术就是要问到你的知识盲区才会停止。

那我们就来画个图表示一下一级缓存

那面试官肯定会说,直接从数据库查不就行了,为啥要一级缓存呢?

当我们使用MyBatis开启一次和数据库的会话时, MyBatis 会创建出一个 SqlSession 对象表示一次与数据库之间的信息传递,在我们执行 SQL 语句的过程中,们可能会反复执行完全相同的查询语句,如果不采取一些措施,我们每一次查询都会查询一次数据库,而如果在极短的时间内做了很多次相同的查询操作,那么这些查询返回的结果很可能相同。

也就是说,如果我们在短时间内,频繁的去执行一条 SQL ,查询返回的结果本来应该是改变了,但是我们查询出来的时候,会出现结果一致的情况,正是为了解决这种问题,也为了减轻数据库的开销,所以 Mybatis 默认开启了一级缓存。

Mybatis 的二级缓存一般如果你不对他进行设置,他是不会开启的,而二级缓存是什么呢?Mybatis 中的二级缓存实际上就是 mapper 级别的缓存,而这时候肯定会有人说,那么不同之间的 Mapper 是同一个缓存么?

答案是否定的,他不是一个,Mapper 级别的缓存实际上就是相同的 Mapper 使用的是一个二级缓存,但是在二级缓存中,又有多个不同的 SqlSession ,而不同的 Mapper 之间的二级缓存也就是互相不会影响的。

就类似下面的图

这二级缓存是不是就看起来有点意思了?

那怎么能够开启二级缓存呢?

1.MyBatis 配置文件

2.MyBatis 要求返回的 POJO 必须是可序列化的

3.Mapper 的 xml 配置文件中加入 标签

既然我们想要了解这个二级缓存,那么必然,我们还得知道它里面的配置都有哪些含义。

我们先从标签看起,然后从源码里面看都有哪些配置信息提供给我们使用:

blocking : 直译就是调度,而在 Mybatis 中,如果缓存中找不到对应的 key ,是否会一直 blocking ,直到有对应的数据进入缓存。

eviction : 缓存回收策略

而缓存回收策略,在源码中是有直接体现的,那么他们分别都对应了什么形式呢?

大家虽然看着 PERPETUAL 排在了第一位,但是它可不是默认的,在 Mybatis 的缓存策略里面,默认的是 LRU 。

PERPETUAL :

源代码如下:

恩?看着是不是有点眼熟,它怎么就只是包装了 HashMap ? 你还别奇怪,他还真的就是使用的 HashMap ,不得不说,虽然人家是使用的 HashMap ,但是那可是比咱们写的高端多了。

既然使用 HashMap ,那么必然就会有Key,那么他们的Key是怎么设计的?

CacheKey:

确实牛逼,至于内部如何初始化,如何进行操作,大家有兴趣的可以去阅读一下源码,导入个源码包,打开自己看一下。

FIFO : 先进先出缓冲淘汰策略

在 FIFO 淘汰策略中使用了 Java 中的 Deque,而 Deque 一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则。Java中,LinkedList实现了Queue接口,因为LinkedList进行插入、删除操作效率较高。

当你看完这个源码的时候,是不是就感觉源码其实也没有那么难看懂,里面都是我们已经掌握好的知识,只不过中间做了一些操作,进行了一些封装。

LRU : 最近最少使用的缓存策略

而 LUR 算法,阿粉之前都说过,如果对这个算法感兴趣的话,文章地址给大家送上,经典的 LRU 算法,你真的了解吗?

而我们需要看的源码则是在 Mybatis 中的源码,

SOFT : 基于垃圾回收器状态和软引用规则的对象

在看到基于垃圾回收器的时候,阿粉就已经开始兴奋了,竟然有GC的事情,那还不赶紧看看,这如此高大上(装杯)的事情,来瞅瞅吧!

WEAK : 基于垃圾收集器状态和弱引用规则的对象

WeakCache在实现上与SoftCache几乎相同,只是把引用对象由SoftReference软引用换成了WeakReference弱引用。

在这里阿粉也就不再多说了,关于 Mybatis 的二级缓存,你了解了么?下次遇到面试官问这个的时候,你应该知道怎么成功(装杯)不被打了吧。

‘拾’ mybatis一级缓存内存占用过大的问题

内存占用过大可以通过flushCache="true"或者where <随机数>=<随机数>去除MyBatis的一级缓存来解决。

1、一级缓存是SqlSession级别的缓存 —— 它是各自独立的。

在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。

不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

2、二级缓存是mapper级别的缓存 —— 它是多个 SqlSession 共享的。

多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

热点内容
java返回this 发布:2025-10-20 08:28:16 浏览:712
制作脚本网站 发布:2025-10-20 08:17:34 浏览:974
python中的init方法 发布:2025-10-20 08:17:33 浏览:685
图案密码什么意思 发布:2025-10-20 08:16:56 浏览:837
怎么清理微信视频缓存 发布:2025-10-20 08:12:37 浏览:743
c语言编译器怎么看执行过程 发布:2025-10-20 08:00:32 浏览:1085
邮箱如何填写发信服务器 发布:2025-10-20 07:45:27 浏览:314
shell脚本入门案例 发布:2025-10-20 07:44:45 浏览:194
怎么上传照片浏览上传 发布:2025-10-20 07:44:03 浏览:882
python股票数据获取 发布:2025-10-20 07:39:44 浏览:840