MyBatis 批量插入时拦截器失效通常由以下几个原因导致:
Executor 类型不同:批量操作通常使用 BatchExecutor
,而普通操作用 SimpleExecutor
或 ReuseExecutor
,拦截器可能没有正确处理不同 Executor 类型
SQL 语句生成方式不同:批量插入可能使用 <foreach>
标签生成动态 SQL,与普通插入语句结构不同
拦截点选择不当:拦截器可能没有覆盖批量操作的关键拦截点
插件配置顺序问题:多个插件间的执行顺序可能影响批量操作
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "flushStatements", args = {})
})
public class BatchInterceptor implements Interceptor {
// 实现逻辑
}
在拦截器中处理 BatchExecutor 的情况:
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof BatchExecutor) {
// 处理批量操作逻辑
}
return invocation.proceed();
}
对于 <foreach>
生成的批量插入语句,需要检查 MappedStatement 的 SQL 命令类型:
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
// 处理插入逻辑
}
确保拦截器在 mybatis-config.xml 中正确配置:
<plugins>
<plugin interceptor="com.example.BatchInterceptor">
<!-- 如果有参数 -->
</plugin>
</plugins>
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "flushStatements", args = {})
})
public class BatchInsertInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
if (ms.getSqlCommandType() == SqlCommandType.INSERT
&& invocation.getTarget() instanceof BatchExecutor) {
// 处理批量插入逻辑
System.out.println("拦截到批量插入操作");
// 可以在这里修改参数或执行其他逻辑
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 可以获取配置的属性
}
}
通过以上方法,应该能够解决 MyBatis 批量插入时拦截器失效的问题。