zoukankan      html  css  js  c++  java
  • Mybatis反射修改SQL值

    Mybatis反射修改SQL值

    某一些情况下我们需要动态的改变Mybtis的执行的sql语句,有两种方法:1)使用拦截器,2)使用反射,拦截器的比较简单点,这里使用反射实现一次,有一点小坑,记录一下:

    特别说明:环境配置就不列出来了,下面的所有操作是假设spring已经整合好了mybatis的基础上的。具体的代码连接见文章结尾:

    重点在于org.apache.ibatis.builder.StaticSqlSource.getBoundSql(Object)

    @Override
      public BoundSql getBoundSql(Object parameterObject) {
        return new BoundSql(configuration, sql, parameterMappings, parameterObject);
      }
    // 每次获得是一个新的对象,这里使用反射修改是无效的,所以需要直接修改 BoundSql 的 sql 子弹
    

    代码:

    @RunWith(SpringJUnit4ClassRunner.class)  
    @ContextConfiguration({"classpath:applicationContext2.xml"})  
    public class MapperTest {
    	
    	@Autowired
    	private SqlSessionFactoryBean sqlSessionFactoryBean;	
    	
    	// 动态修改sql 
    	// 1. 使用 mybatis 的插件来完成参考分页插件改变查询的SQL com.bart.plugins.MyBatisPagePlugi
    	// 2. 使用反射修改MappedStatement的boundSql
    	@Test 
    	public void testDynamicModifySQL2() throws Exception {
    		SqlSessionFactory sessionFactory = sqlSessionFactoryBean.getObject();
    		Configuration configuration = sessionFactory.getConfiguration();
    		MappedStatement mappedStatement = configuration.getMappedStatement("com.bart.common.mapper.dao.EmployeeMapper.selectAll");
    		// org.apache.ibatis.scripting.defaults.RawSqlSource
    		// 该 sqlSource 中还有一个 org.apache.ibatis.builder.StaticSqlSource 实例
    		// getSqlSource() 实际上是调用的内部的 StaticSqlSource#getSqlSource() 方法
    		// 而StaticSqlSource#getSqlSource()每次返回的是一个新的BoundSql对象直接修改这个
    		// 是无效的,所以我们需要使用反射直接修改那个 StaticSqlSource 中的 sql 字符串的值
    		SqlSource rowSqlSource = mappedStatement.getSqlSource();
    		System.out.println(String.format("修改前的SQL = %s", rowSqlSource.getBoundSql(null).getSql()));
    		// 获得 private final SqlSource sqlSource; 对象
    		Field staticsqlSourceField = rowSqlSource.getClass().getDeclaredField("sqlSource");
    		staticsqlSourceField.setAccessible(true);
    		Object staticsqlSourceObject = staticsqlSourceField.get(rowSqlSource);
    		
    		// 修改 sqlSource 的 sql 字段值
    		Field sqlField = staticsqlSourceObject.getClass().getDeclaredField("sql");
    		sqlField.setAccessible(true);
    		String sqlFieldValue = (String)sqlField.get(staticsqlSourceObject);
    		sqlField.set(staticsqlSourceObject, sqlFieldValue +" limit 1");
    		
    		System.out.println(String.format("修改前的SQL = %s", rowSqlSource.getBoundSql(null).getSql()));
    		System.out.println("============分割线===============");
    		List<Employee> list = employeeMapper.selectAll();
    		list.stream().forEach(System.out::println); // 查询出来就是一条了OK
    		
    	}
    

    代码具体实现

  • 相关阅读:
    [ 黑盒测试方法 ] 错误猜测法
    [ 黑盒测试方法 ] 边界值分析法
    [ 黑盒测试方法 ] 等价类划分法
    [ Python入门教程 ] Python面向对象编程(下)
    [ Python入门教程 ] Python面向对象编程(上)
    [ Python入门教程 ] Python模块定义和使用
    [ Python入门教程 ] Python常用内置函数介绍
    [ Python入门教程 ] Python函数定义和使用
    MyBatis的缓存分析
    微机原理与接口技术总计
  • 原文地址:https://www.cnblogs.com/bartggg/p/12996777.html
Copyright © 2011-2022 走看看