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
    		
    	}
    

    代码具体实现

  • 相关阅读:
    poj 3280 Cheapest Palindrome(区间DP)
    POJ 2392 Space Elevator(多重背包)
    HDU 1285 定比赛名次(拓扑排序)
    HDU 2680 Choose the best route(最短路)
    hdu 2899 Strange fuction (三分)
    HDU 4540 威威猫系列故事――打地鼠(DP)
    HDU 3485 Count 101(递推)
    POJ 1315 Don't Get Rooked(dfs)
    脱离eclipse,手动写一个servlet
    解析xml,几种方式
  • 原文地址:https://www.cnblogs.com/bartggg/p/12996777.html
Copyright © 2011-2022 走看看