开发的时候,写Mybatis Mapper.xml文件的时候,每次修改SQL都需要重启服务,感觉十分麻烦,于是尝试写了一个Mybatis的Mapper.xml热加载。

能在修改Mapper.xml之后重新加载Mybatis,开发的时候可以用一下。

Spring配置:

<bean id="MybatisMapperDynamicLoader" class="com.teststartup.MybatisMapperDynamicLoader" />

Java代码:

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask; import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.NestedIOException;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver; public class MybatisMapperDynamicLoader implements InitializingBean, ApplicationContextAware { private final HashMap<String, String> mappers = new HashMap<String, String>();
private volatile ConfigurableApplicationContext context = null;
private volatile Scanner scanner = null; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = (ConfigurableApplicationContext) applicationContext;
} @Override
public void afterPropertiesSet() throws Exception {
try {
scanner = new Scanner();
new Timer(true).schedule(new TimerTask() {
public void run() {
try {
if (scanner.isChanged()) {
System.out.println("load mapper.xml");
scanner.reloadXML();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, 10 * 1000, 5 * 1000);
} catch (Exception e1) {
e1.printStackTrace();
}
} @SuppressWarnings("unchecked")
class Scanner {
private static final String XML_RESOURCE_PATTERN = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/*Sql.xml";
private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
public Scanner() throws IOException {
Resource[] resources = findResource();
if (resources != null) {
for (Resource resource : resources) {
String key = resource.getURI().toString();
String value = getMd(resource);
mappers.put(key, value);
}
}
}
public void reloadXML() throws Exception {
SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
Configuration configuration = factory.getConfiguration();
removeConfig(configuration);
for (Resource resource : findResource()) {
try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(), configuration, resource.toString(), configuration.getSqlFragments());
xmlMapperBuilder.parse();
} finally {
ErrorContext.instance().reset();
}
}
}
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");
}
private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
Field field = classConfig.getDeclaredField(fieldName);
field.setAccessible(true);
((Map) field.get(configuration)).clear();
}
private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
Field field = classConfig.getDeclaredField(fieldName);
field.setAccessible(true);
((Set) field.get(configuration)).clear();
}
public boolean isChanged() throws IOException {
boolean isChanged = false;
for (Resource resource : findResource()) {
String key = resource.getURI().toString();
String value = getMd(resource);
if (!value.equals(mappers.get(key))) {
isChanged = true;
mappers.put(key, value);
}
}
return isChanged;
}
private Resource[] findResource() throws IOException {
return resourcePatternResolver.getResources(XML_RESOURCE_PATTERN);
}
private String getMd(Resource resource) throws IOException {
return new StringBuilder().append(resource.contentLength()).append("-").append(resource.lastModified()).toString();
}
}
}

最新文章

  1. SharePoint 2013 JavaScript API 记录
  2. 【C语言】C语言运算符
  3. 简述frame、bounds、center
  4. 关于showModalDialog()对话框点击按钮弹出新页面的问题
  5. SQL 获取各表记录数的最快方法
  6. 你真的理解z-index吗?
  7. 分享一些Comet开发经验
  8. Android系列之Fragment(一)----Fragment加载到Activity当中
  9. ABAP DEBUG
  10. Oracle- 初识
  11. echshop jquery与transpart冲突解决?
  12. uvalive 2322 Wooden Sticks(贪心)
  13. Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
  14. windows下安装zabbix_agent
  15. Azkaban 2.5.0 搭建和一些小问题
  16. Go语言中的面向对象
  17. scrapy 命令行基本用法
  18. 【推荐】HTML5 Word Cloud——中文词云
  19. liunx 安装Zabbix的心酸历程
  20. 项目总结07:JS图片的上传预览和表单提交(FileReader()方法)

热门文章

  1. JQuery插件:动态列和无间隙网格布局Mason.js
  2. 无废话MVC入门教程一[概述、环境安装、创建项目]
  3. Unity5.1 新的网络引擎UNET(九) UNET 官方推荐视频教程
  4. JMeter 四:建立高级web测试计划
  5. Spring IOC、对象依赖关系
  6. Unity命令行模式,也能「日志实时输出」
  7. 算法笔记_075:蓝桥杯练习 最短路(Java)
  8. Java基础——线程总结
  9. 老项目转为maven的步骤具体说明
  10. 学会Git玩转Github笔记(三)—— Github Pages 搭建个人网站