文档章节

Mybatis热加载Mapper.xml

G
 Galanodel
发布于 2017/05/05 09:35
字数 407
阅读 24
收藏 0

开发的时候,写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();
		}
	}
}

 

© 著作权归作者所有

共有 人打赏支持
G
粉丝 2
博文 72
码字总数 49356
作品 0
海淀
高级程序员
私信 提问
Mybatis-Plus 1.4.5 发布,支持 mybatis 热加载等

Mybatis-Plus 1.4.5 发布了。 支持 mybatis mapper.xml 单个方法修改热加载,支持公共字段自定义填充功能。数据库关键词转义等!!! Mybatis-Plus 是一款 MyBatis 的增强工具包,简化 CURD...

青苗
2016/08/29
4.9K
7
Mybatis 入门案例 2 ---- mapper 代理的方式

我们只需要编写DAO接口和mapper.xml文件即可,DAO接口实现对象由mybatis自动生成代理对象。 如: 一、为什么不使用原始的DAO方式开发呢? 1、dao的实现类中存在重复代码,整个mybatis操作的过...

故新
2017/11/07
0
0
mybatis学习笔记(2)-mybatis概述

mybatis学习笔记(2)-mybatis概述 标签: mybatis [TOC] 本文对mybatis做一个简单介绍,包括框架原理,执行过程,开发方法,输入输出映射以及动态sql,我会在后续的系列文章中一一详细说明 my...

brianway
2016/02/27
334
0
MyBaits基本概念和原理

什么是MyBatis? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XM...

sun2shadows
2017/09/14
0
0
Spring+mybatis测试项目总结

1.项目目的 a.通过Spring+Mybatis实现通过web访问达成mySql的操作 b.理解Spring+Mybatis的配置 c.理解maven对项目的管理 2.配置文件 a.采用maven约定结构,src/main/java、src/main/resource...

飓风2000
2014/07/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux iptables之mangle表使用案例

mangle表的用途 mangle表的主要功能是根据规则修改数据包的一些标志位,以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 mangel表使用示例 示例1-策略路由1 内网的客户机通...

月下狼
56分钟前
3
0
OSChina 周日乱弹 —— 兼职我想去学学布偶戏

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @clouddyy : 《火炎 - 女王蜂》 《火炎 - 女王蜂》 手机党少年们想听歌,请使劲儿戳(这里) @小鱼丁 :还在睡觉突然接到一个小哥哥电话“x...

小小编辑
今天
69
5
租房软件隐私保护如同虚设

近日,苏州市民赵先生向江苏新闻广播新闻热线025-84658888反映,他在“安居客”手机应用软件上浏览二手房信息,并且使用该软件自动生成的虚拟号码向当地一家中介公司进行咨询。可电话刚挂不久...

linux-tao
今天
3
0
分布式项目(五)iot-pgsql

书接上回,在Mapping server中,我们已经把数据都整理好了,现在利用postgresql存储历史数据。 iot-pgsql 构建iot-pgsql模块,这里我们写数据库为了性能考虑不在使用mybatis,换成spring jd...

lelinked
今天
6
0
一文分析java基础面试题中易出错考点

前言 这篇文章主要针对的是笔试题中出现的通过查看代码执行结果选择正确答案题材。 正式进入题目内容: 1、(单选题)下面代码的输出结果是什么? public class Base { private Strin...

一看就喷亏的小猿
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部