MyBatis SQL 热替换

MyBatis SQL 热替换
-----------------------
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();

}

}

}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值