(转)mybatis热部署加载*Mapper.xml文件,手动刷新*Mapper.xml文件

转自: https://blog.csdn.net/LOVELONG8808/article/details/78738086 


由于项目已经发布到线上,要是修改一个Mapper.xml文件的话,需要重启整个服务,这个是很耗时间的,而且在一段时间内导致服务不可用,严重影响用户的体验度。所以希望可以有一个机制可以,当修改某个mapper.xml的时候,只要重新加载这个mapper.xml就好了,参考网上的一些资料和demo,加上一些自己的总结,下面的代码是通过测试的,可以供你们参考和使用。

import java.io.IOException;  
import java.lang.reflect.Field;  
import java.util.ArrayList;
import java.util.HashMap;  
import java.util.List;
import java.util.Map;  
import java.util.Set;  import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.apache.ibatis.builder.xml.XMLMapperBuilder;  
import org.apache.ibatis.session.Configuration;  
import org.apache.ibatis.session.SqlSessionFactory;  
import org.springframework.core.io.Resource;  
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;  public class RefreshMapperCache {  private Log log  = LogFactory.getLog(RefreshMapperCache.class);  private SqlSessionFactory sqlSessionFactory;  private Resource[] mapperLocations;  private String packageSearchPath;  private HashMap<String, Long> fileMapping = new HashMap<String, Long>();// 记录文件是否变化  //记录发生改变的xml文件名称private List<String> changeResourceNameList = new ArrayList<>();public void refreshMapper() {  try {  Configuration configuration = this.sqlSessionFactory.getConfiguration();  // step.1 扫描文件  try {  this.scanMapperXml();  } catch (IOException e) {  log.error("packageSearchPath扫描包路径配置错误");  return;  }  //            System.out.println("==============刷新前mapper中的内容 start===============");  
//            //获取xml中的每个语句的名称即 id = "findUserById";
//            for (String name : configuration.getMappedStatementNames()) {  
//                System.out.println(name);  
//            }  
//            System.out.println("==============刷新前mapper中的内容   end===============");  //清空被修改过后的文件名称,确保该集合是空的changeResourceNameList.clear();// step.2 判断是否有文件发生了变化  if (this.isChanged()) {  // step.2.1 清理  this.removeConfig(configuration);  // step.2.2 重新加载  for (Resource configLocation : mapperLocations) {  try { //匹配被修改过的mapper文件,如果存在,则重新加载//如果想要重新加载全部mapper,可以不匹配if(changeResourceNameList.contains(configLocation.getFilename())){XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configLocation.getInputStream(), configuration, configLocation.toString(), configuration.getSqlFragments());  xmlMapperBuilder.parse();  System.out.println("mapper文件[" + configLocation.getFilename() + "]缓存加载成功");  }} catch (IOException e) {  System.out.println("mapper文件[" + configLocation.getFilename() + "]不存在或内容格式不对");  continue;  }  }//清空被修改过后的文件名称changeResourceNameList.clear();}  //            System.out.println("--------------------------刷新后mapper中的内容 start--------------------------");  
//            for (String name : configuration.getMappedStatementNames()) {  
//                System.out.println(name);  
//            }
//            System.out.println("--------------------------刷新后mapper中的内容  end--------------------------");   } catch (Exception e) {  System.out.println("****************刷新缓存异常: "+e.getMessage());}  }  public void setPackageSearchPath(String packageSearchPath) {  this.packageSearchPath = packageSearchPath;  }  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {  this.sqlSessionFactory = sqlSessionFactory;  }  /** * 扫描xml文件所在的路径 * @throws IOException  */  private void scanMapperXml() throws IOException {  this.mapperLocations = new PathMatchingResourcePatternResolver().getResources(packageSearchPath);  }  /** * 清空Configuration中几个重要的缓存 * @param configuration * @throws Exception */  private void removeConfig(Configuration configuration) throws Exception {  Class<?> classConfig = configuration.getClass();  clearMap(classConfig, configuration, "mappedStatements");  clearMap(classConfig, configuration, "caches");  clearMap(classConfig, configuration, "resultMaps");  clearMap(classConfig, configuration, "parameterMaps");  clearMap(classConfig, configuration, "keyGenerators");  clearMap(classConfig, configuration, "sqlFragments");  clearSet(classConfig, configuration, "loadedResources");  }  @SuppressWarnings("rawtypes")  private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {  Field field = classConfig.getDeclaredField(fieldName);  field.setAccessible(true);  Map mapConfig = (Map) field.get(configuration);  mapConfig.clear();  }  @SuppressWarnings("rawtypes")  private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {  Field field = classConfig.getDeclaredField(fieldName);  field.setAccessible(true);  Set setConfig = (Set) field.get(configuration);  setConfig.clear();  }  /** * 判断文件是否发生了变化 * @param resource * @return * @throws IOException */  private boolean isChanged() throws IOException {  boolean flag = false;  System.out.println("***************************获取文件名   开始************************************");for (Resource resource : mapperLocations) {  String resourceName = resource.getFilename();  System.out.println("resourceName == " + resourceName+",  path = "+resource.getURL().getPath());boolean addFlag = !fileMapping.containsKey(resourceName);// 此为新增标识  // 修改文件:判断文件内容是否有变化  Long compareFrame = fileMapping.get(resourceName);  long lastFrame = resource.contentLength() + resource.lastModified();  boolean modifyFlag = null != compareFrame && compareFrame.longValue() != lastFrame;// 此为修改标识  if(addFlag){System.out.println("            新增了:==="+ resourceName);}if(modifyFlag){System.out.println("            修改了:==="+ resourceName);}// 新增或是修改时,存储文件  if(addFlag || modifyFlag) {  fileMapping.put(resourceName, Long.valueOf(lastFrame));// 文件内容帧值  flag = true;  changeResourceNameList.add(resourceName);}  } System.out.println("***************************获取文件名   结束************************************");return flag;  }  
}  

写一个实体类,然后在spring中配置改实体类的bean即可
 

    <bean id="refreshMapperCache" class="com.company.project.util.RefreshMapperCache" >  <!-- 扫描的映射mapper.xml的文件路径这个地方要注意mapper的文件,多数据源情况下,只能扫描自己数据源下的mapper,否则会报异常          --><property name="packageSearchPath" value="classpath*:mapper/trade/**/*.xml"></property><!-- 配置自己的数据源 --><property name="sqlSessionFactory" ref="sqlSessionFactoryPay"></property>  </bean>  


由于我们公司使用的是多数据源,所以在配置bean的时候,要给每个数据源配置一个bean,注意点就是在配置bean的时候

1. 如果是多数据源的情况 ,  扫描mapper.xml文件的时候,只能扫该数据源下的mapper.xml文件

2. 多数据源情况想,设置sqlSessionFactory 的时候,要设置为对应的数据源

3. 如果是但数据源的情况,那么就简单了,只需要配置当前数据源及对应的mapper.xml文件即可
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图解HashMap和HashSet的内部工作机制

转载自 图解HashMap和HashSet的内部工作机制HashMap 和 HashSet 内部是如何工作的&#xff1f;散列函数&#xff08;hashing function&#xff09;是什么&#xff1f; HashMap 不仅是一个常用的数据结构&#xff0c;在面试中也是热门话题。 Q1. HashMap 如何存储数据&#xff1…

window location href 手机端无法跳转_Window对象在前端领域的角色

特殊的window提起window&#xff0c;在网页当中很常见&#xff0c;比如像这样&#xff1a;window.onloadfunction(){ //执行函数体 }这段代码的意思是当网页内容加载完成后要做什么。在js的领域&#xff0c;window对象有着双重角色&#xff0c;既是用来访问浏览器窗口的接口&am…

leetcode初级算法2.旋转数组

leecode初级算法2.旋转数组 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我自己的解法&#xff1a; public static void rotate(int[] nums, int k) {int move k % nums.length;Stack<Integer> stack new Stack<>();if(move 0){return;}else {f…

java运行环境变量及自定义变量

【README】 本文主要介绍java运行环境变量的获取&#xff0c;如何读取 env.properties 文件并将自定义变量写入到系统变量&#xff1b; 【1】System.getenv() 获取环境变量 public static void main1() {Map<String, String> envMap System.getenv();envMap.entrySet(…

Java HashSet和HashMap源码剖析

转载自 Java HashSet和HashMap源码剖析总体介绍 之所以把HashSet和HashMap放在一起讲解&#xff0c;是因为二者在Java里有着相同的实现&#xff0c;前者仅仅是对后者做了一层包装&#xff0c;也就是说HashSet里面有一个HashMap&#xff08;适配器模式&#xff09;。因此本文将重…

怎么把页面按比例缩小_meta viewport 是做什么用的,怎么写?

前置知识&#xff08;有助于viewport的理解&#xff09;李明&#xff1a;设备像素、设备独立像素、CSS像素、分辨率、PPI、devicePixelRatio​zhuanlan.zhihu.com移动端的问题屏幕窄&#xff0c;一般来说设备独立像素不超过400px。比如把网站侧边栏宽度设置为10%&#xff0c;这…

(转)java动态代理与aop

转自&#xff1a; Java 动态代理与AOP - 如果的事 - 博客园动态代理与AOP 代理模式 代理模式给某一个目标对象(target)提供代理对象(proxy)&#xff0c;并由代理对象控制对target对象的引用。 模式图&#xff1a; 代理模式中的角色有&#xff1a; 抽象对象角色(Abstrachttps://…

ConcurrentHashMap的红黑树实现分析

转载自 ConcurrentHashMap的红黑树实现分析红黑树 红黑树是一种特殊的二叉树&#xff0c;主要用它存储有序的数据&#xff0c;提供高效的数据检索&#xff0c;时间复杂度为O(lgn)&#xff0c;每个节点都有一个标识位表示颜色&#xff0c;红色或黑色&#xff0c;有如下5种特性&a…

leetcode初级算法3.存在重复元素

leetcode初级算法3.存在重复元素 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a; Arrays.sort(nums);for(int i 0; i < nums.length-1; i){if(nums[i] nums[i1]){return true;}}return false;官方题解&#xff1a; public boolean con…

sql server累计求和函数_SQL基础--SQL高级功能

一.窗口函数有什么用&#xff1f;在日常工作中&#xff0c;经常会遇到需要在每组内排名&#xff0c;比如下面的业务需求&#xff1a;排名问题&#xff1a;每个部门按业绩来排名topN问题&#xff1a;找出每个部门排名前N的员工进行奖励面对这类需求&#xff0c;就需要使用sql的高…

(转)【SpringMvc】如何使用form发送PUT和DELETE请求

转自&#xff1a; https://blog.csdn.net/cockroach02/article/details/82194126https://blog.csdn.net/cockroach02/article/details/82194126 一、当前现状 浏览器使用form提交信息的时候只支持GET和POST&#xff0c;如果需要在浏览器上使用PUT和DELETE请求方式的话&#…

leetcode初级算法4.只出现一次的数字

leetcode初级算法4.只出现一次的数字 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a; public static int singleNumber(int[] nums) {if(nums.length 1){return nums[0];}Arrays.sort(nums);int slow 0;int fast 1;while(fast < nums.…

集合总结(Collection)

转载自 集合总结(Collection) 最近项目上线完&#xff0c;闲来无事&#xff0c;整理了关于集合相关对比&#xff0c;具体详见以下几点&#xff1a;1.ArrayList和Vector区别&#xff1a;这两个类都实现了List接口(List接口继承了Collection接口)&#xff0c;他们都是有序集合&am…

springboot接收浏览器发送delete请求( method not allowed 405解决方法)

【README】 浏览器使用form提交信息的时候只支持GET和POST&#xff0c;如果需要在浏览器上使用PUT和DELETE请求方式的话&#xff0c;只能使用欺骗的方式了&#xff0c;SpringMvc提供了HiddenHttpMethodFilter类来提供支持&#xff1b; 【1】前端 1&#xff09;list.html <…

tensorflow图形检测_社交距离检测器——Tensorflow检测模型设计

在隔离期间&#xff0c;我花时间在github上探索Tensorflow的大量预训练模型。这样做时&#xff0c;我偶然发现了一个包含25 个带有性能和速度指标的预训练对象检测模型的存储库。拥有一些计算机视觉知识并给出了实际的背景知识&#xff0c;我认为使用其中之一来构建社交隔离应用…

leetcode初级算法4.两个数组的交集 II

leetcode初级算法4.两个数组的交集 II 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a;&#xff08;总结在代码中&#xff09; public int[] intersect(int[] nums1, int[] nums2) {//为空则返回if(nums1 null || nums2 null){return null;…

Java NIO:Buffer、Channel 和 Selector

转载自 Java NIO&#xff1a;Buffer、Channel 和 Selector本文将介绍 Java NIO 中三大组件 Buffer、Channel、Selector 的使用。 本来要一起介绍非阻塞 IO 和 JDK7 的异步 IO 的&#xff0c;不过因为之前的文章真的太长了&#xff0c;有点影响读者阅读&#xff0c;所以这里将它…

(转)使用IDEA将普通MAVEN项目转为WEB项目

转自&#xff1a; 使用IDEA将普通MAVEN项目转为WEB项目_yun0000000的博客-CSDN博客使用IDEA将普通MAVEN项目转为WEB项目https://blog.csdn.net/yun0000000/article/details/70664944 1、file--project Structure--,然后点“”号&#xff0c;,若没有war包&#xff0c;可修改mav…

python创建文件对象_python基础教程:文件读写

在Linux系统中&#xff0c;一切都是文件。但我们通常说的文件是保存在磁盘上的图片、文档、数据、程序等等。而在程序的IO操作中&#xff0c;很多时候就是从磁盘读写文件。本节我们讲解Python中的文件对象如何操作文件。创建文件对象 通过Python内置函数open()可以很容易的创建…

(转)springboot:添加JSP支持

转自&#xff1a; 14.springboot:添加JSP支持 - 简书&#xff08;1&#xff09;创建Maven web project 使用Eclipse新建一个Maven Web Project &#xff0c;项目取名为&#xff1a;spring-boot-jsp &#xff08;2&#xff09;在pom.xm...https://www.jianshu.com/p/4216bbd1e0…