zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
  • 相关阅读:
    App唤起微信小程序和回调
    微信小程序 — 自定义picker选择器弹窗内容+textarea穿透bug
    微信小程序的场景值scene
    微信小程序textarea层级过高(盖住其他元素)
    微信小程序如何修改本地缓存key中的单个数据
    微信小程序---查看更多的显示与隐藏
    微信小程序文字超过行后隐藏并且显示省略号
    Flutter 页面下拉刷新和上拉加载
    json转换成dart类 JSON to Dart
    Flutter 保持页面状态
  • 原文地址:https://www.cnblogs.com/relucent/p/4108187.html
Copyright © 2011-2022 走看看