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 }

代码具体实现

最新文章

  1. ASP DropDownList部分选项无法触发回传问题
  2. Python基础语法
  3. LUA+resty 搭建验证码服务器
  4. 地图API文档
  5. chrome浏览器不允许记忆登录账户的方法
  6. SSAS建模遇到的问题集锦
  7. c#分页读取GB文本文件
  8. app:transformClassesWithJarMergingForDebug uplicate entry: android/support/v4/app/BackStackState$1.class
  9. C#读取和写入配置文件
  10. 使用AmplifyJS和JQuery编写更好更优雅的javascript事件处理代码
  11. 【Unity3D】场景转换与退出
  12. js 随手记
  13. 记关于 Lambda 表达式的基础写法
  14. 超链接访问过后hover样式就不出现的问题是什么?如何解决?
  15. POI/Excel/HTML单元格公式问题
  16. ViewPager+Fragment 懒加载
  17. Go 嵌入类型
  18. Chrome调试WebView时Inspect出现空白的解决方法(使用离线包不Fan墙)
  19. Java内存管理之类似-Xms、-Xmx 这些参数的含义
  20. 给1~3年iOS开发 经验朋友们的一些建议(附BAT面试题)

热门文章

  1. 24个经典的MySQL索引问题,你都遇到过哪些?
  2. Reflux之Store
  3. Codeforces1157A(A题)Reachable Numbers
  4. Django之ORM属性类型和约束条件
  5. A + B Problem(hdu1000)
  6. 杨辉三角(hdu2032)——有待完善
  7. pyenv,轻松切换各种python版本
  8. Spring bean工厂配置头文件
  9. C#正则表达式基础
  10. KVM的常用操作