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
		
	}

代碼具體實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM