shouwangV 2016-02-11
MyBatisSQL热替换
-----------------------
package cn.bisoft.ibatis; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.ibatis.binding.MapperProxyFactory; import org.apache.ibatis.binding.MapperRegistry; import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.executor.keygen.KeyGenerator; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMap; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.parsing.XNode; import org.apache.ibatis.session.Configuration; import cn.bisoft.util.CollectionUtil; import cn.bisoft.util.ReflectUtil; public final class ConfigurationRefactor { private static final String FIELD_LOADED_RESOURCES = "loadedResources"; private static final String FIELD_MAPPER_REGISTRY = "mapperRegistry"; private static final String FIELD_KNOW_MAPPERS = "knownMappers"; private static final String FIELD_MAPPED_STATEMENTS = "mappedStatements"; private static final String FIELD_CACHES = "caches"; private static final String FIELD_RESULT_MAPS = "resultMaps"; private static final String FIELD_PARAMETER_MAPS = "parameterMaps"; private static final String FIELD_KEY_GENERATORS = "keyGenerators"; private static final String FIELD_SQL_FRAGMENTS = "sqlFragments"; /** * 热替换MyBatis的SQL.新增加Mapper暂时不适用. * * @param conf Configuration * @param name Mapper 完全限定类名 * @throws Exception */ public void replaceMapper(Configuration conf, String name) throws Exception { Class<?> type = conf.getClass().getClassLoader().loadClass(name); if (null != type) { // 1. lock configuration synchronized (conf.getClass()) { // 2. 清除配置的Mapper资源标志 String resource = type.toString(); if (conf.isResourceLoaded(resource)) { // 利用反射修改 Set<String> loadedResources = (Set<String>) ReflectUtil .get(conf, FIELD_LOADED_RESOURCES); loadedResources.remove(resource); } else { // PASS } // 3. 清除Mapper资源 if (conf.hasMapper(type)) { MapperRegistry mapperRegistry = (MapperRegistry) ReflectUtil .get(conf, FIELD_MAPPER_REGISTRY); Map<Class<?>, MapperProxyFactory<?>> knownMappers = (Map<Class<?>, MapperProxyFactory<?>>) ReflectUtil .get(conf, FIELD_KNOW_MAPPERS); knownMappers.put(type, new MapperProxyFactory(type)); } // 4. 清除语句 Map<String, MappedStatement> mappedStatements = (Map<String, MappedStatement>) ReflectUtil .get(conf, FIELD_MAPPED_STATEMENTS); Map<String, MappedStatement> mappedStatementsDup = CollectionUtil .cloneMap(mappedStatements); ReflectUtil.set(conf, FIELD_MAPPED_STATEMENTS, mappedStatementsDup, true); // 5. 清除缓存 Map<String, Cache> caches = (Map<String, Cache>) ReflectUtil .get(conf, FIELD_CACHES); Map<String, Cache> cachesDup = CollectionUtil.cloneMap(caches); ReflectUtil.set(conf, FIELD_CACHES, new HashMap<String, Cache>(), true); // 6. 清除结果 Map<String, ResultMap> resultMaps = (Map<String, ResultMap>) ReflectUtil .get(conf, FIELD_RESULT_MAPS); Map<String, ResultMap> resultMapsDup = CollectionUtil .cloneMap(resultMaps); ReflectUtil.set(conf, FIELD_RESULT_MAPS, resultMapsDup, true); // 7. 清除参数 Map<String, ParameterMap> parameterMaps = (Map<String, ParameterMap>) ReflectUtil .get(conf, FIELD_PARAMETER_MAPS); Map<String, ParameterMap> parameterMapsDup = CollectionUtil .cloneMap(parameterMaps); ReflectUtil .set(conf, FIELD_PARAMETER_MAPS, resultMapsDup, true); // 8. 清除主键 Map<String, KeyGenerator> keyGenerators = (Map<String, KeyGenerator>) ReflectUtil .get(conf, FIELD_KEY_GENERATORS); Map<String, KeyGenerator> keyGeneratorsDup = CollectionUtil .cloneMap(keyGenerators); ReflectUtil .set(conf, FIELD_KEY_GENERATORS, resultMapsDup, true); // 9. 清除SQL Map<String, XNode> sqlFragments = (Map<String, XNode>) ReflectUtil .get(conf, FIELD_SQL_FRAGMENTS); Map<String, XNode> sqlFragmentsDup = CollectionUtil .cloneMap(sqlFragments); ReflectUtil.set(conf, FIELD_SQL_FRAGMENTS, resultMapsDup, true); // 10. 重新加载配置 MapperAnnotationBuilder parser = new MapperAnnotationBuilder( conf, type); parser.parse(); } } } }