当前使用版本(必填,否则不予处理)
3.5.5
该问题是如何引起的?(确定最新版也有问题再提!!!)
在执行updateBatchById时,多个的数据更新,变动插件只能看到第一个数据
重现步骤(如果有就写完整)
- 执行iserice的updateBatchById的接口
报错信息
无
Comment From: Jasonyou-boy
提供一下具体场景或代码
Comment From: jackmiking
自动回复:你的邮件我已经收到,如果需要回复的我会尽快回复的。感谢你的谅解····
Comment From: MrXiaoMo
目前使用版本为3.5.5,使用updateBatchById更新多条数据时,只能拦截第一条更新SQL
Comment From: CalmArrow
应该不只是updateBatchById方法,所有与batch相关的方法在处理批量操作时,只会拦第一条数据 这个问题我也遇到了,有什么解决方法吗?
Comment From: totoro52
```
import com.baomidou.mybatisplus.core.toolkit.PluginUtils; import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal; import com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInnerInterceptor; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.update.Update; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType;
import java.sql.Connection; import java.sql.SQLException;
/ * @author Totoro * @date 2024/6/3 * @description / public class CustomDataChangeInnerInterceptor extends DataChangeRecorderInnerInterceptor {
@Override
public void beforeGetBoundSql(StatementHandler sh) {
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
// 补充connection
Connection connection;
try {
connection = mpSh.configuration().getEnvironment().getDataSource().getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
MappedStatement ms = mpSh.mappedStatement();
final BoundSql boundSql = mpSh.boundSql();
SqlCommandType sct = ms.getSqlCommandType();
if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
OperationResult operationResult;
long startTs = System.currentTimeMillis();
try {
Statement statement = JsqlParserGlobal.parse(mpBs.sql());
if (statement instanceof Insert) {
operationResult = processInsert((Insert) statement, mpSh.boundSql());
} else if (statement instanceof Update) {
operationResult = processUpdate((Update) statement, ms, boundSql, connection);
} else if (statement instanceof Delete) {
operationResult = processDelete((Delete) statement, ms, boundSql, connection);
} else {
logger.info("other operation sql={}", mpBs.sql());
return;
}
} catch (Exception e) {
if (e instanceof DataUpdateLimitationException) {
throw (DataUpdateLimitationException) e;
}
logger.error("Unexpected error for mappedStatement={}, sql={}", ms.getId(), mpBs.sql(), e);
return;
}
long costThis = System.currentTimeMillis() - startTs;
if (operationResult != null) {
operationResult.setCost(costThis);
dealOperationResult(operationResult);
}
}
}
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
// 我什么都不干
}
} ````
看了下源代码,InnerInterceptor#beforePrepare这个方法一般作用是修改执行的SQL,但这个插件有点特殊,它还需要回查数据,但beforePrepare只拿到了首条数据,因为最终去执行的是updateById方法。能拿到的数据很有限,所以我也没想到好点解决的方法。。 你可以先用这个方法暂时解决问题,其实就是把beforePrepare的代码搬到beforeGetBoundSql方法,需要注意的是这里的connection不是同一个。
Comment From: VampireAchao
DataChangeRecorderInnerInterceptor可能在未来版本将会被移除,坑有点大
Comment From: jackmiking
自动回复:你的邮件我已经收到,如果需要回复的我会尽快回复的。感谢你的谅解····
Comment From: nieqiurong
6430
Comment From: cc1aymore
```
import com.baomidou.mybatisplus.core.toolkit.PluginUtils; import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal; import com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInnerInterceptor; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.update.Update; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType;
import java.sql.Connection; import java.sql.SQLException;
/ * @author Totoro * @date 2024/6/3 * @description / public class CustomDataChangeInnerInterceptor extends DataChangeRecorderInnerInterceptor {
@Override public void beforeGetBoundSql(StatementHandler sh) { PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); // 补充connection Connection connection; try { connection = mpSh.configuration().getEnvironment().getDataSource().getConnection(); } catch (SQLException e) { throw new RuntimeException(e); } MappedStatement ms = mpSh.mappedStatement(); final BoundSql boundSql = mpSh.boundSql(); SqlCommandType sct = ms.getSqlCommandType(); if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) { PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); OperationResult operationResult; long startTs = System.currentTimeMillis(); try { Statement statement = JsqlParserGlobal.parse(mpBs.sql()); if (statement instanceof Insert) { operationResult = processInsert((Insert) statement, mpSh.boundSql()); } else if (statement instanceof Update) { operationResult = processUpdate((Update) statement, ms, boundSql, connection); } else if (statement instanceof Delete) { operationResult = processDelete((Delete) statement, ms, boundSql, connection); } else { logger.info("other operation sql={}", mpBs.sql()); return; } } catch (Exception e) { if (e instanceof DataUpdateLimitationException) { throw (DataUpdateLimitationException) e; } logger.error("Unexpected error for mappedStatement={}, sql={}", ms.getId(), mpBs.sql(), e); return; } long costThis = System.currentTimeMillis() - startTs; if (operationResult != null) { operationResult.setCost(costThis); dealOperationResult(operationResult); } } } @Override public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { // 我什么都不干 }
} ```
看了下源代码,InnerInterceptor#beforePrepare这个方法一般作用是修改执行的SQL,但这个插件有点特殊,它还需要回查数据,但beforePrepare只拿到了首条数据,因为最终去执行的是updateById方法。能拿到的数据很有限,所以我也没想到好点解决的方法。。 你可以先用这个方法暂时解决问题,其实就是把beforePrepare的代码搬到beforeGetBoundSql方法,需要注意的是这里的connection不是同一个。
有问题,三次update后 ,mpSh.configuration().getEnvironment().getDataSource().getConnection(); 这里会卡死