`

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();

			}

		}

	}

}
 
 
分享到:
评论

相关推荐

    mybatis 日志 sql参数替换工具

    非常好用的,就是你们所要的 Mybatis日志参数快速替换占位符 sql参数替换工具html

    mybatis替换问号完整Sql插件

    &lt;plugin interceptor="com.zheling.interceptor.FullSQLInterceptor"/&gt;

    mybatissql_mybatis解决sql注入

    标题 "mybatissql_mybatis解决sql注入" 暗示了我们正在讨论MyBatis框架如何处理SQL注入问题。SQL注入是一种常见的安全漏洞,攻击者可以通过恶意输入篡改SQL查询,获取、修改或删除数据库中的敏感数据。MyBatis,作为...

    ideal mybatis打印sql插件

    把 mybatis 输出的sql日志还原成完整的sql语句。 将日志输出的sql语句中的问号 ? 替换成真正的参数值。 通过 "Tools -&gt; MyBatis Log Plugin" 菜单或快捷键 "Ctrl+Shift+Alt+O" 启用。 点击窗口左边的 "Filter" ...

    MyBatis连接SQLServer的小例子

    MyBatis是一款优秀的Java持久层框架,它支持定制化SQL、存储过程以及高级映射,极大地简化了传统Java开发中的数据库操作。SQLServer是微软公司推出的关系型数据库管理系统,广泛应用于企业级应用开发。本教程将通过...

    详解MyBatis直接执行SQL查询及数据批量插入

    MyBatis是一个强大的持久层框架,它允许开发者直接编写SQL语句,简化了数据库操作。在本文中,我们将深入探讨如何使用MyBatis直接执行SQL查询以及如何进行数据的批量插入。 **一、直接执行SQL查询** 在MyBatis中,...

    Mybatis中执行String类型的自己拼写的sql,不执行配置文件中的sql

    这里,`sqlSessionFactory`是MyBatis的会话工厂,`params`可以是用于占位符替换的参数对象。使用这种方式,我们可以在代码中动态构建和执行SQL。 执行自定义SQL而不是XML配置文件中的SQL有以下优点: 1. 动态性:在...

    idea插件mybaits log 打印sql语句

    标题 "idea插件mybaits log 打印sql语句" 涉及的是一个针对IntelliJ IDEA的MyBatis日志插件,它的主要功能是帮助开发者在开发过程中实时查看并打印出MyBatis执行的SQL语句。这个功能对于调试和优化数据库查询非常...

    SpringBoot +Mybatis xml方式配置SQL Demo源码下载

    在本文中,我们将深入探讨如何在SpringBoot项目中结合Mybatis框架进行XML方式的SQL配置。SpringBoot以其简洁的配置和强大的自动配置能力,极大地简化了应用开发过程,而Mybatis作为一款轻量级的持久层框架,允许...

    mybatis如何防止SQL注入

    `会被实际的参数值所替换,而SQL语句本身则提前编译好了。由于预编译SQL只允许合法的SQL语法,因此可以有效防止SQL注入。 ##### 2. 避免使用脚本变量(Scripting Variables) 在MyBatis中,除了`#{}`之外还可以使用...

    Mybatis日志参数快速替换占位符工具的详细步骤

    Mybatis日志参数快速替换占位符工具是一个实用的辅助工具,它可以帮助开发者在调试过程中更方便地查看和理解Mybatis执行的SQL语句。在默认的日志输出中,Mybatis使用占位符(?)表示传入的参数,这在某些情况下可能...

    MyBatis通过 JDBC连接 SQL server 数据库 最小例子

    MyBatis是一个流行的Java持久层框架,它简化了与数据库之间的交互,允许开发者将SQL查询直接集成到Java代码中。本教程将引导你通过JDBC连接到SQL Server 2005数据库,创建一个最小的例子来展示MyBatis的基本用法。 ...

    mybatis-log-plugin:将Mybatis SQL日志还原到原始的整个可执行SQL

    还原MyBatis输出的日志为完整的SQL语句。 把SQL日志里面的?替换为真正的参数值。 选中要还原的MyBatis日志,右键点击菜单Restore Sql,还原SQL语句. Java接口方法与Mapper xml文件互相跳转。 按钮作用 Text: 从文本...

    MyBatis拦截器分页与动态修改SQL及其参数值

    在MyBatis框架中,拦截器(Interceptor)是一种强大的工具,可以用来在SQL执行的生命周期内插入自定义逻辑。在本主题中,我们将探讨如何利用MyBatis拦截器实现分页查询、动态修改SQL以及调整参数值。这些功能对于...

    mybatis修改了mapper xml不用重启tomcat,热发布热更新.zip_mybatis的xml模糊查询

    mybatis修改了mapper xml不用重启tomcat,热发布热更新.zip

    mybatis 实现 SQL 查询拦截修改详解

    在MyBatis框架中,SQL查询拦截修改是一种高级特性,它允许开发者在SQL执行的特定阶段插入自定义的逻辑,如添加额外的日志记录、性能分析、安全性检查等。这主要是通过实现`Interceptor`接口来完成的。 `Interceptor...

    mybatis自动生成

    把 mybatis 输出的sql日志还原成完整的sql语句。 将日志输出的sql语句中的问号 ? 替换成真正的参数值。 通过 "Tools -&gt; MyBatis Log Plugin" 菜单或快捷键 "Ctrl+Shift+Alt+O" 启用。 点击窗口左边的 "Filter" ...

    SpringBoot整合MybatisSQL过滤@Intercepts的实现

    这里,我们创建了一个名为`copyFromMappedStatement`的方法,它使用MappedStatement.Builder来构建一个新的MappedStatement对象,同时保持原有配置不变,只是替换掉SQL源。 在实际应用中,这个SqlInterceptor可以...

    mybatis拦截器修改执行sql语句

    通过mybatis拦截器将查询语句、更新语句、删除语句、插入语句中指定表明替换为另一个表名

    spring boot中配置mybatis热加载相关文件

    在Spring Boot应用中,MyBatis作为持久层框架,通常会使用XML文件来定义SQL映射。然而,当开发过程中需要频繁修改这些XML文件时,每次改动都需要重启服务才能看到效果,这无疑降低了开发效率。为了解决这个问题,...

Global site tag (gtag.js) - Google Analytics