最近在做一个项目,为处理并发性较差的问题,使用了Mybatis二级缓存

但在多表联合查询的情况下,Mybatis二级缓存是存在着数据脏读的问题的

两天就是在想办法解决这个数据脏读的问题

考虑到简易性、性能、兼容性、可扩展性,我选择了springboot自带的 Ehcache 框架来整合解决这个问题

我也是第一次接触到 Ehcache 这个框架,所以也算从零开始

根据Mybatis二级缓存的特点,我的思路是

  每当 增删改 某张表 , 就清除刷新其关联的所有表的 缓存

( 这里可分为两个大小方向:

在 增删改 的方法上,做相关的 关联清除缓存 操作  ——  这个就比较细节化一点,做的修改可能会比较多

在 增删改方法 所在类的整体上,做相关的 关联清除缓存操作  —— 这个我需要做的修改就相对少点,但这样里面每个方法(包括一些无关紧要的)都会触发这个清除缓存操作

都各有利弊 )

一路上并不顺利,

一开始我尝试自己看能不能找到比较好的方法,但刚接触一下子就自己解决也是不太可能的

但有看到一个解决Mybatis二级缓存问题的插件 —— GitHub上 LuanLouis 的 mybatis-enhanced-cache

但这个project是5年前写的,而且最近一次更新也只是2年前,现在技术发展那么快,看到的时候就感觉可能不行

后面自己也下载了下来,mvn install 发现不成功,缺少ojdbc14的jar包 ,网上说ojdbc14.jar 是收费的,所以中央库是导不了这个包

看了一些资料说,Oracle安装目录里面有,但公司这台没装Oracle ;也有资料说,可以用 ojdbc6 或其他ojdbc代替,我就下载了ojdbc6 和ojdbc8 都试了一下,都能够解决那个ojdbc jar包的问题,

mybatis-enhanced-cache 插件的jar也成功导入了maven库和项目中,但导入之后,用的时候却又发现报各种错,就觉得凉了,

本来就是为了简单快速,才想用别人的插件,所以我不可能自己又去修改这个插件来用,改了又不一定能用!所以使用插件这个方案就只能放弃了

后来,又找了网上很多资料,也按很多示例的步骤做了

像各种注解、各种配置什么的,都不知道是和mybatis的注解冲突了,还是我写的无效

(像网上很多资料说的,mybatis二级缓存是不推荐使用的,至于为什么我还要用,可以看我前面一篇文章——  缓存的设计与使用  ,

所以在方面遇到我这样问题的应该没几个,也就找不到多少资料,只能靠自己)

想了很多可能性,试了一次又一次,想尽量做得简单点,直接简单XML配置加注解 ,能够这样就好了。

但现实是残酷的,做了不知多少次的尝试,还是没成功,无计可施,最后还是只能放弃这个方案了

没有办法,就只能选择最后一种方案了 —— 自己写代码,在业务逻辑层 做处理

这对一无所知的菜鸟,也不容易啊

好在坚持尝试,最后终于找到解决方案

配置 ehcache.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!-- <ehcache> -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"> <!--
磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存
path:指定在硬盘上存储对象的路径
path可以配置的目录有:
user.home(用户的家目录)
user.dir(用户当前的工作目录)
java.io.tmpdir(默认的临时目录)
ehcache.disk.store.dir(ehcache的配置目录)
绝对路径(如:d:\\ehcache)
查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir");
-->
<diskStore path="java.io.tmpdir" /> <!-- 配置提供者 1、peerDiscovery,提供者方式,有两种方式:自动发现(automatic)、手动配置(manual) 2、rmiUrls,手动方式时提供者的地址,多个的话用|隔开 -->
<!-- <cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:40002/userCache" /> -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446,timeToLive=255"/>
<!-- <cacheManagerPeerProviderFactory
class="org.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446,timeToLive=255"/> --> <!-- 配置监听器 1、hostName 主机地址 2、port 端口 3、socketTimeoutMillis socket子模块的超时时间,默认是2000ms -->
<!-- <cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=127.0.0.1, port=40001, socketTimeoutMillis=2000" /> -->
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/> <!--
defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理
maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象
eternal:代表对象是否永不过期 (指定true则下面两项配置需为0无限期)
timeToIdleSeconds:最大的闲置时间 /秒
timeToLiveSeconds:最大的存活时间 /秒
overflowToDisk:是否允许对象被写入到磁盘
说明:下列配置自缓存建立起600秒(10分钟)有效 。
在有效的600秒(10分钟)内,如果连续120秒(2分钟)未访问缓存,则缓存失效。
就算有访问,也只会存活600秒。
-->
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="true" /> <cache name="*.*.*.*.dao.WarnMapper" maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="300" overflowToDisk="true" /> <cache name="*.*.*.*.dao.ProjectMapper" maxElementsInMemory="10000" eternal="false"
          timeToIdleSeconds="120" timeToLiveSeconds="300" overflowToDisk="true" />
</ehcache>

配置 application.properties

 # Ehcache缓存
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:/ehcache.xml

业务逻辑层代码

 package *.*.*.common.utils;

 import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager; public class EhcacheUtil { // 构建一个缓存管理器
private static CacheManager cacheManager = CacheManager.newInstance("src/main/resources/ehcache.xml"); /**
* action 清除相关联的缓存
* @param cacheName 缓存所在namespace的名称
* @param keys 缓存所在namespace下key的名称,为空则默认清空所有key
* @return
*/
public static void clearRelatedCache( String cacheName, String[] keys ) {
Cache cache = cacheManager.getCache(cacheName) ;
if ( cache==null ) {
return ;
}
//若缓存不为空
if ( keys==null || keys.length==0 ) {
cache.removeAll();
}
else {
for (String key : keys) {
cache.remove(key) ;
}
}
} }
 1    @PostMapping("/delete")
public Result delete(HttpServletRequest request) {
Long projectId = StringUtil.getLong(request.getParameter("id")) ;
Project project = projectService.findById(projectId) ;
if(project==null) {
return ResultGenerator.genFailResult(ResultCode.UNAUTHORIZED, "工程id不正确");
}
projectService.deleteById(projectId);;
EhcacheUtil.clearRelatedCache(CacheConstants.CACHE_NAMESPACE_WARNMAPPER, null) ;
return ResultGenerator.genSuccessResult("删除成功");
}

共同学习,共同进步,若有补充,欢迎指出,谢谢!

Springboot + Mybatis + Ehcache的更多相关文章

  1. Shiro+springboot+mybatis+EhCache(md5+salt+散列)认证与授权-03

    从上文:Shiro+springboot+mybatis(md5+salt+散列)认证与授权-02 当每次进行刷新时,都会从数据库重新查询数据进行授权操作,这样无疑给数据库造成很大的压力,所以需要引入 ...

  2. springboot+mybatis+ehcache实现缓存数据

    一.springboot缓存简介 在 Spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓 ...

  3. springboot+mybatis+redis实现分布式缓存

    大家都知道springboot项目都是微服务部署,A服务和B服务分开部署,那么它们如何更新或者获取共有模块的缓存数据,或者给A服务做分布式集群负载,如何确保A服务的所有集群都能同步公共模块的缓存数据, ...

  4. spring boot学习(十三)SpringBoot缓存(EhCache 2.x 篇)

    SpringBoot 缓存(EhCache 2.x 篇) SpringBoot 缓存 在 Spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManag ...

  5. (转)springMVC+mybatis+ehcache详细配置

    一. Mybatis+Ehcache配置 为了提高MyBatis的性能,有时候我们需要加入缓存支持,目前用的比较多的缓存莫过于ehcache缓存了,ehcache性能强大,而且位各种应用都提供了解决方 ...

  6. 第五章 springboot + mybatis(转载)

    本编博客转发自:http://www.cnblogs.com/java-zhao/p/5350021.html springboot集成了springJDBC与JPA,但是没有集成mybatis,所以 ...

  7. 第九章 springboot + mybatis + 多数据源 (AOP实现)

    在第八章 springboot + mybatis + 多数据源代码的基础上,做两点修改 1.ShopDao package com.xxx.firstboot.dao; import org.spr ...

  8. 第五章 springboot + mybatis

    springboot集成了springJDBC与JPA,但是没有集成mybatis,所以想要使用mybatis就要自己去集成.集成方式相当简单. 1.项目结构 2.pom.xml <!-- 与数 ...

  9. 基于Maven的Springboot+Mybatis+Druid+Swagger2+mybatis-generator框架环境搭建

    基于Maven的Springboot+Mybatis+Druid+Swagger2+mybatis-generator框架环境搭建 前言 最近做回后台开发,重新抓起以前学过的SSM(Spring+Sp ...

随机推荐

  1. PHP学习(3)——数据的存储与检索

    要点目录: I.保存数据 II.打开文件   III.创建并写入文件 IV.关闭文件 V.读文件 VI.给文件加锁 VII.删除文件 VIII.其他有用的文件操作函数 IX.数据库管理系统 1.保存数 ...

  2. iterm 2快捷键

    快捷键 作用说明 command + f 搜索&查找,如果输入搜索内容后,按下 tab 键,就会 iTerm 自动帮选中搜索关键词,并且自动的帮我们复制到了剪贴板中.如果输入的是 shift+ ...

  3. python中 __file__的小坑坑

    在python脚本中,我们难免会需要用到自身文件所在的绝对路径,第一想法可能就是用os.path.dirname(__file__) 但是这里有个大坑,我就踩了,这种方式得到路径会出现问题,脚本执行报 ...

  4. linux-关闭文件

    1.打开参考: http://q.cnblogs.com/q/39275/ http://hi.baidu.com/auxor/item/49b6e929fdf16dc7ed10f197 2.关闭参考 ...

  5. ESXi 制作模板并优化 Centos

    1.修改网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 #编辑network配置文件修改以下两项 (eth1同理) ONBOOT=yes BOOTP ...

  6. [转帖]查看Linux用的桌面是GNOME、KDE或者其他

    http://superuser.com/questions/96151/how-do-i-check-whether-i-am-using-kde-or-gnome KDE 基于QT做的 已经越来越 ...

  7. spark-scala-java实现wordcount

    引入:spark-scala-java实现wordcount 1.spark-scala实现wordcount package com.cw.scala.spark import org.apache ...

  8. linux node 安装

    百度搜索出来的按照方式都是下载linux的解压包后,解压出可执行文件然后创建软连接, 我试了一下不知为何node可以创建软连接,但是npm 创建软连接执行不了 还是使用官方的安装方式成功了 https ...

  9. 怎样修改输入框 placehoder 提示文本的颜色?

    1. 在这个问题上, 不同浏览器的设置方法有所差异, 可以写成下面这种形式. ::-webkit-input-placeholder { /* WebKit browsers */ color: #9 ...

  10. 区间问题 codeforces 422c+hiho区间求差问

    先给出一个经典的区间处理方法 对每个区间 我们对其起点用绿色标识  终点用蓝色标识 然后把所有的点离散在一个坐标轴上 如下图 这样做有什么意义呢.由于我们的区间可以离散的放在一条轴上面那么我们在枚举区 ...