mybatis实现mapper文件热部署
来源:互联网 发布:百度地图数据采集器 编辑:程序博客网 时间:2024/04/29 03:20
每次修改mybatis的sql脚本后,都要重启,因为mybatis的mapper文件默认只在启动时加载到缓存,改动后不会自动加载,于是研究了下mybatis配置文件的加载,分享如下:实现思路:使用定时器定时扫描mapper文件的改动,如果有改动则调用mapper文件的加载方法XMLMapperBuilder.parse()。一.写一个重新加载mapper文件的java类 首先需要构建一个sqlSessionFactory对象,并指定mybatis的Configuration.xml配置文件路径,之后定时扫描并判断mapper文件是否有改动,如果有改动则重新加载,代码如下:package zttc.itat.user.utils;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;import org.apache.ibatis.builder.xml.XMLMapperBuilder;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.apache.log4j.Logger;import org.springframework.core.io.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;/** * mybatis的mapper文件有改动时,进行重新加载 * @author ycblus * */public class SqlSessionCache { private Logger log = Logger.getLogger(SqlSessionCache.class); private Resource[] mapperLocations; private String packageSearchPath = "classpath*:zttc/itat/user/mapper/*.xml"; SqlSessionFactory sqlSessionFactory; Configuration configuration; private HashMap<String, Long> fileMapping = new HashMap<String, Long>();// 记录文件是否变化 { String resource = "Configuration.xml"; InputStream inputStream; try { inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream) ; configuration = this.sqlSessionFactory.getConfiguration(); //扫描文件 } catch (IOException e) { e.printStackTrace(); } } public void refreshMapper() throws Exception{ try { try { this.scanMapperXml(); } catch (IOException e) { log.error("packageSearchPath扫描包路径配置错误"); return; } Runnable runnable = new Runnable() { public void run() { // task to run goes here try { // 判断是否有文件发生了变化 if (isChanged()) { // 清理 this.removeConfig(configuration); // 重新加载 for (Resource configLocation : mapperLocations) { try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configLocation.getInputStream(), configuration, configLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); log.info("mapper文件[" + configLocation.getFilename() + "]加载成功"); } catch (IOException e) { log.error("mapper文件[" + configLocation.getFilename() + "]不存在或内容格式不对"); continue; } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 清空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"); } /** * 判断文件是否发生了变化 * @param resource * @return * @throws IOException */ boolean isChanged() throws IOException { boolean flag = false; for (Resource resource : mapperLocations) { String resourceName = resource.getFilename(); boolean addFlag = !fileMapping.isEmpty() && !fileMapping.containsKey(resourceName);// 此为新增标识 // 修改文件:判断文件内容是否有变化 Long compareFrame = fileMapping.get(resourceName); long lastFrame = resource.contentLength() + resource.lastModified(); boolean modifyFlag = null != compareFrame && compareFrame.longValue() != lastFrame;// 此为修改标识 fileMapping.put(resourceName, Long.valueOf(lastFrame));// 文件内容帧值 // 新增或是修改时,存储文件 if(addFlag || modifyFlag) { flag = true; } } return flag; } }; ScheduledExecutorService service = Executors .newSingleThreadScheduledExecutor(); // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间 service.scheduleAtFixedRate(runnable, 1, 10, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); } } 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(); } public static void main(String[] args) { HashMap<String, Long> fileMapping = new HashMap<String, Long>(); boolean f = !fileMapping.isEmpty() && !fileMapping.containsKey("Hello.xml"); System.out.println(f); }} 二.Configuration.xml配置文件这个配置文件在这里只作为扫描配置使用,可以看到其他配置都没有,因为我是在spring里面统一配置了<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <mappers> <mapper resource="zttc/itat/user/mapper/TUserMapper.xml"/> <mapper resource="zttc/itat/user/mapper/TStoreMapper.xml"/> </mappers> </configuration>三.写一个Servlet,在服务器启动时调用前面写好的定时加载类。代码如下: package zttc.itat.user.servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.apache.log4j.Logger;import zttc.itat.user.utils.SqlSessionCache;/** * Servlet implementation class MapperReloadServlet * * when mybatis files changed,reload them */public class MapperReloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public MapperReloadServlet() { super(); // TODO Auto-generated constructor stub } public void init()throws ServletException { Logger logger = Logger.getLogger(this.getClass()); logger.info("The mapper reload timer starting... "); try { new SqlSessionCache().refreshMapper(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}此外,需在web.xml中加入这个servlet类,添加代码如下: <servlet> <servlet-name>MapperReloadServlet</servlet-name> <servlet-class>zttc.itat.user.servlet.MapperReloadServlet</servlet-class> <load-on-startup>7</load-on-startup> </servlet> 这样每次当mapper文件有改动时,就会重新加载。不过会把所有的mapper文件重新加载一遍,如果需要对指定文件进行加载也是可以的,需要修改下重新加载的类。
0 0
- mybatis实现mapper文件热部署
- mybatis实现mapper文件热部署
- mybatis实现mapper文件热部署
- mybatis热部署加载*Mapper.xml文件
- SpringMVC+Mybatis+热部署mapper文件
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- mybatis热部署加载*Mapper.xml文件,手动刷新*Mapper.xml文件
- Mybatis热加载Mapper.xml
- Mybatis - Mapper文件简练
- MyBatis Mapper 文件例子
- tomcat热部署实现文件下载
- MyBatis之XML文件配置实现映射器Mapper
- MyBatis Mapper XML 文件 01
- MyBatis Mapper XML 文件 02
- 链表删除,反序操作等
- Cookie扫盲贴
- 自定义Loading Dialog
- 涉及的物理、数学公式及计算过程
- ubuntu或者deepin的一些常用操作命令
- mybatis实现mapper文件热部署
- Jenkins Gitlab持续集成打包平台搭建
- android音频降噪webrtc
- 利用Console来调试JS程序、Console用法总结(1)
- 交叉熵
- spring中@param和mybatis中@param使用区别
- Leetcode 461. Hamming Distance
- Git tag 给当前分支打标签
- UVa 116 Unidirectional TSP