`
zhangfeilo
  • 浏览: 391126 次
  • 性别: Icon_minigender_1
  • 来自: 昆明
社区版块
存档分类
最新评论

Mybatis配置文件修改后自动加载

阅读更多
Mybatis的mapper文件中的sql语句被修改后, 只能重启服务器才能被加载, 非常耗时,所以就写了一个自动加载的类,
配置后检查xml文件更改,如果发生变化,重新加载xml里面的内容.在Mybatis3.1.1上测试.
package cn.common.dao;
 
import java.io.IOException;
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.executor.ErrorContext;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
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;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
 
/**
 * @version 2013年11月10日 下午1:43:45
 */
@Service
public class XMLMapperLoader implements DisposableBean, InitializingBean, ApplicationContextAware {
 
    private ConfigurableApplicationContext context = null;
    private transient String basePackage = null;
    private HashMap<String, String> fileMapping = new HashMap<String, String>();
    private Scanner scanner = null;
    private ScheduledExecutorService service = null;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = (ConfigurableApplicationContext) applicationContext;
 
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            service = Executors.newScheduledThreadPool(1);
            // 获取xml所在包
            MapperScannerConfigurer config = context.getBean(MapperScannerConfigurer.class);
            Field field = config.getClass().getDeclaredField("basePackage");
            field.setAccessible(true);
            basePackage = (String) field.get(config);
            // 触发文件监听事件
            scanner = new Scanner();
            scanner.scan();
 
            service.scheduleAtFixedRate(new Task(), 5, 5, TimeUnit.SECONDS);
 
        } catch (Exception e1) {
            e1.printStackTrace();
        }
 
    }
 
    class Task implements Runnable {
        @Override
        public void run() {
            try {
                if (scanner.isChanged()) {
                    System.out.println("*Mapper.xml文件改变,重新加载.");
                    scanner.reloadXML();
                    System.out.println("加载完毕.");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
 
    }
 
    @SuppressWarnings({ "rawtypes" })
    class Scanner {
        private String[] basePackages;
        private static final String XML_RESOURCE_PATTERN = "**/*.xml";
        private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 
        public Scanner() {
            basePackages = StringUtils.tokenizeToStringArray(XMLMapperLoader.this.basePackage,
                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        }
 
        public Resource[] getResource(String basePackage, String pattern) throws IOException {
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                    + ClassUtils.convertClassNameToResourcePath(context.getEnvironment().resolveRequiredPlaceholders(
                            basePackage)) + "/" + pattern;
            Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
            return resources;
        }
 
        public void reloadXML() throws Exception {
            SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
            Configuration configuration = factory.getConfiguration();
            // 移除加载项
            removeConfig(configuration);
            // 重新扫描加载
            for (String basePackage : basePackages) {
                Resource[] resources = getResource(basePackage, XML_RESOURCE_PATTERN);
                if (resources != null) {
                    for (int i = 0; i < resources.length; i++) {
                        if (resources[i] == null) {
                            continue;
                        }
                        try {
                            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resources[i].getInputStream(),
                                    configuration, resources[i].toString(), configuration.getSqlFragments());
                            xmlMapperBuilder.parse();
                        } catch (Exception e) {
                            throw new NestedIOException("Failed to parse mapping resource: '" + resources[i] + "'", e);
                        } 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 mapConfig = (Map) field.get(configuration);
            mapConfig.clear();
        }
 
        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 void scan() throws IOException {
            if (!fileMapping.isEmpty()) {
                return;
            }
            for (String basePackage : basePackages) {
                Resource[] resources = getResource(basePackage, XML_RESOURCE_PATTERN);
                if (resources != null) {
                    for (int i = 0; i < resources.length; i++) {
                        String multi_key = getValue(resources[i]);
                        fileMapping.put(resources[i].getFilename(), multi_key);
                    }
                }
            }
        }
 
        private String getValue(Resource resource) throws IOException {
            String contentLength = String.valueOf((resource.contentLength()));
            String lastModified = String.valueOf((resource.lastModified()));
            return new StringBuilder(contentLength).append(lastModified).toString();
        }
 
        public boolean isChanged() throws IOException {
            boolean isChanged = false;
            for (String basePackage : basePackages) {
                Resource[] resources = getResource(basePackage, XML_RESOURCE_PATTERN);
                if (resources != null) {
                    for (int i = 0; i < resources.length; i++) {
                        String name = resources[i].getFilename();
                        String value = fileMapping.get(name);
                        String multi_key = getValue(resources[i]);
                        if (!multi_key.equals(value)) {
                            isChanged = true;
                            fileMapping.put(name, multi_key);
                        }
                    }
                }
            }
            return isChanged;
        }
    }
 
    @Override
    public void destroy() throws Exception {
        if (service != null) {
            service.shutdownNow();
        }
    }
 
}
 来源:https://www.oschina.net/code/snippet_1018034_26472
import java.lang.reflect.Field;
 
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
 
public class SqlSessionFactoryBeanExt extends SqlSessionFactoryBean {
 
    private SqlSessionFactory sqlSessionFactory;
 
    public void setValue(String name, Object value) {
        try {
            Field field = SqlSessionFactoryBean.class.getDeclaredField(name);
            field.setAccessible(true);
            field.set(this, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
            sqlSessionFactory = buildSqlSessionFactory();
            setValue("sqlSessionFactory", sqlSessionFactory);
        }
        return this.sqlSessionFactory;
    }
 
    public void afterPropertiesSet() throws Exception {
    }
 
}
 
 
分享到:
评论

相关推荐

    mybatis的具体介绍.doc

    简单易用:通过XML配置文件和注解,MyBatis让开发者能够轻松地将SQL语句与Java代码分离,使得代码结构更清晰、易于维护。 映射简单:MyBatis提供了简单的映射方式,可以将数据库表中的字段自动映射到Java对象的...

    JAVA Spring框架实现登陆查询 完整搭建框架方法的word文档 包含mysql文件

    3 导入配置文件,将如下配置文件导入到src下面 3.1 修改generatorConfig.xml文件,这个是mybatis的逆向工程,修改数据库名,用户名,密码,对应的包名,对应的项目。如图 3.2 修改jdbc.properits文件, 3.3 log...

    Mybatis-plus(Mybatis增强工具包) v3.3.2

    修改在Mybatis全局配置文件中设置分页插件参数不生效问题 修改在Mybatis全局配置文件中设置分页插件参数不生效问 修复PR未指定解析器的时候引发空指针 增加分页插件limit参数配置 修复指定superEntityClass重复...

    springboot知识点整理

    2.9 配置文件的加载位置 33 2.10 外部配置加载顺序 36 2.11 自动配置原理 37 2.12 @Conditional派生注解 41 3 Spring Boot与日志 42 3.1 日志框架分类和选择 42 3.2 SLF4j使用 43 3.3 其他日志框架统一转换成slf4j+...

    SpringBoot学习视频

    尚硅谷_SpringBoot_配置-配置文件的加载位置 尚硅谷_SpringBoot_配置-外部配置加载顺序 尚硅谷_SpringBoot_配置-自动配置原理 尚硅谷_SpringBoot_配置-@Conditional&自动配置报告 尚硅谷_SpringBoot_日志-日志框架...

    尚硅谷springboot视频(上)

    尚硅谷_SpringBoot_配置-配置文件的加载位置 尚硅谷_SpringBoot_配置-外部配置加载顺序 尚硅谷_SpringBoot_配置-自动配置原理 尚硅谷_SpringBoot_配置-@Conditional&自动配置报告 尚硅谷_SpringBoot_日志-日志框架...

    128元尚硅谷Java视频教程_SpringBoot视频教程(上)核心技术篇

    内容包含微服务概念、配置文件、日志框架的使用、web开发、Thymeleaf模板引擎、Docker容器技术、MyBatis、Spring Data JPA、自定义starter等; 00、尚硅谷_SpringBoot_源码、课件 01、尚硅谷_SpringBoot_入门-课程...

    尚硅谷Spring boot核心技术篇(上)

    14、尚硅谷_SpringBoot_配置-@PropertySource、@ImportResource、@Bean 15、尚硅谷_SpringBoot_配置-配置文件占位符 16、尚硅谷_SpringBoot_配置-Profile多环境支持 17、尚硅谷_SpringBoot_配置-配置文件的加载位置 ...

    企业后台管理基础框架 hsweb.zip

    通用mybatis配置文件,支持多种条件查询自动生成,支持自动生成insert,update,delete语句,支持和查询相同的各种条件.实现用户,权限管理;基于aop,注解,精确到按钮的权限控制.动态表单功能,可在前端设计表单,动态生成...

    Java SpringBoot课件+源码视频教程

    17、_SpringBoot_配置-配置文件的加载位置 18、_SpringBoot_配置-外部配置加载顺序 19、_SpringBoot_配置-自动配置原理 6 o* r% s4 }/ ]! Z8 N 20、_SpringBoot_配置-@Conditional&自动配置报告 21、_SpringBoot_...

    jfinal demo 3.2

    自动加载修改后的java文件,开发过程中无需重启web server AOP支持,拦截器配置灵活,功能强大 Plugin体系结构,扩展性强 多视图支持,支持FreeMarker、JSP、Velocity 强大的Validator后端校验功能 功能齐全,...

    topfox快速开发框架

    热加载 支持在不使用devtools/jrebel的情况下, 热加载 mybatis的mapper文件 内置全局、局部拦截插件:提供delete、update 自定义拦截功能 拥有预防Sql注入攻击功能 无缝支持spring cloud: 后续提供分布式调用的例子

    基于SpringBoot+Mybatis开发的主从架构的Steam商城,详情请看README+源代码+文档说明+数据库sql

    然后导入sql文件,修改相应的的配置,关于主从配置请自行百度啦,运行起项目,然后需要把`GameService`类以及`CommentService`类里面的`afterPropertiesSet`方法里面的代码注释掉,这是第一次启动加载缓存的代码。...

    topfox快速开发平台例子 topfox-sample.zip

    - **热加载** 支持在不使用devtools/jrebel的情况下, 热加载 mybatis的mapper文件 - 内置全局、局部拦截插件:提供delete、update 自定义拦截功能 - **拥有预防Sql注入攻击功能** - **无缝支持spring cloud**: 后续...

    Java项目:轻语音乐网平台(java+Springboot+ssm+mysql+maven+jsp)

    播放页面背景为模 糊背景,根据歌手的专辑图片自动变化。 二、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql + Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts 都支持) 项目技术: JSP +SpringBoot + MyBatis +...

    基于SpringBoot开发的长途汽车售票系统源码+sql数据库+项目说明+设计报告.zip

    2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。...

    jeesuite-libs-其他

    自动切换故障节点支持多节点下并行计算支持无注册中心单机模式支持自定义重试策略支持配置持久化(启动加载、变更保存)支持控制台(jeesuite-admin)任务监控、开停、动态修改调度时间策略、手动触发执行jeesuite-...

    Spring.3.x企业应用开发实战(完整版).part2

    2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 2.3.2 UserDao 2.3.3 LoginLogDao 2.3.4 在Spring中装配DAO 2.4 业务层 2.4.1 UserService 2.4.2 在Spring中装配Service 2.4.3 单元测试 2.5 展现层 ...

    Spring3.x企业应用开发实战(完整版) part1

    2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 2.3.2 UserDao 2.3.3 LoginLogDao 2.3.4 在Spring中装配DAO 2.4 业务层 2.4.1 UserService 2.4.2 在Spring中装配Service 2.4.3 单元测试 2.5 展现层 ...

    Java常见面试题208道.docx

    107.spring boot 配置文件有哪几种类型?它们有什么区别? 108.spring boot 有哪些方式可以实现热部署? 109.jpa 和 hibernate 有什么区别? 110.什么是 spring cloud? 111.spring cloud 断路器的作用是什么? 112....

Global site tag (gtag.js) - Google Analytics