首页 > 代码库 > Mybatis热加载Mapper.xml

Mybatis热加载Mapper.xml

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

 

Mybatis热加载Mapper.xml