mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案

问题产生背景:

在开发一个sdk的时候,里面会用到mybatis的拦截器对数据库返回的数据进行相关的处理,公司另一个团队的系统需要接入sdk,但是接入的时候发现,该系统本身也有对mybatis拦截器对处理,而且也是处理sql的返回数据,这样导致插件sdk用原来的方式获取sql的时候就会出现异常。

sdk的拦截器:

sdk自定义拦截器的intercepter中会对返回的resulSettHandler处理mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第1张图片

 首先需要拿到当前请求的sql:

按照这种方式是可以拿到sql的。

正常情况下是这样的:

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第2张图片

也就是可以拿到具体的Sql的。

但是由于sdk中有mybatis的拦截器,接入系统也有mybatis的拦截器,且也是对返回的resultSetHandler进行处理。

 

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第3张图片 

这就导致了在获取sql的时候出现异常 

java.lang.NoSuchFieldException: boundSql
	at java.lang.Class.getDeclaredField(Class.java:2070)

debug的时候,发现,这个时候的target获取后并不是一个具体的resultsethandler对象,而是一个proxy的plugin,点开h后才能看到具体想要的那些,

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第4张图片

这样就获取不到sql了。

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第5张图片 

经debug发现,在添加拦截器的时候

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第6张图片 

如果是处理同一个的话,就会进行第二次代理,这样就导致我们在取sql的时候,拿出来的是一个代理plugin。

经过观察, 系统自定义的拦截器总是在sdk拦截器后执行,然后我把取sql的代码从sdk放到系统自定义的拦截器里面,发现可以正常渠道sql,也就是说,如果把sdk的拦截器执行顺序放到系统自定义的后面,那应该也可以,试验后发现,是可以的。

那么接下来就是调整两个拦截器执行顺序的问题了,两个方法:

1.xml文件配置

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第7张图片

在xml文件中配置两个拦截器,配置在前面的后执行,配置在后面的先执行。 

2.代码中添加

因为sdk不可能为这样一个系统专门改造,且sdk的拦截器是自动添加到sqlSession里面的,之前系统中的拦截器也是自动添加的,这时候添加顺序是先添加系统的,然后添加sdk的,现在改个顺序,让系统自带的变为手动添加。

首先去掉系统自带的拦截器的注解:

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第8张图片

然后手动添加:

mybatis多个拦截器执行顺序以及获取sql出现java.lang.NoSuchFieldException: boundSql异常问题解决方案_第9张图片 这样sdk的拦截器就变为后执行,能够正常获取sql。

成功解决问题。 

你可能感兴趣的:(异常处理,java试题,SpringBoot,mybatis,sql,数据库,java,spring)