AHUTwzw opened a new issue, #36101:
URL: https://github.com/apache/shardingsphere/issues/36101
ShardingJDBC+Mybatis-Plus------The problem can be reproduced, but it is not
clear what operation logic triggers it.
In the project, a very simple `saveBatch()` function occasionally throws the
error "Too many keys are generated." Through breakpoints, it was found that
when the exception occurs, the `generatedValues` in
`ShardingSpherePreparedStatement` is not empty, and the previously cached
result is returned, causing the error. In the `executeBatch()` method, only
`statements.clear()` is executed in the callback. Neither the `clearPrevious()`
method is used before execution as in the `executeUpdate()` and
`executeQuery()` methods to clear the cached objects, nor is it cleared in the
`finally` block. I don't understand why this is done. In our project, the
`saveBatch()` method is used extensively, which has brought great uncertainty
to the stability and security of our project. The following is part of the
source code.
```
@Override
public int[] executeBatch() throws SQLException {
try {
return executeBatchExecutor.executeBatch(usedDatabase,
sqlStatementContext, generatedValues, statementOption,
(StatementAddCallback<PreparedStatement>) (statements,
parameterSets) -> this.statements.addAll(statements),
this::replaySetParameter,
() -> {
currentBatchGeneratedKeysResultSet =
getGeneratedKeys();
statements.clear();
});
// CHECKSTYLE:OFF
} catch (final RuntimeException ex) {
// CHECKSTYLE:ON
handleExceptionInTransaction(connection, metaData);
throw SQLExceptionTransformEngine.toSQLException(ex,
usedDatabase.getProtocolType());
} finally {
clearBatch();
}
}
```
```
private void clearPrevious() {
currentResultSet = null;
statements.clear();
parameterSets.clear();
generatedValues.clear();
}
```
```
@Override
public ResultSet executeQuery() throws SQLException {
try {
if (statementsCacheable && !statements.isEmpty()) {
resetParameters();
return statements.iterator().next().executeQuery();
}
clearPrevious();
QueryContext queryContext = createQueryContext();
handleAutoCommit(queryContext.getSqlStatementContext().getSqlStatement());
findGeneratedKey().ifPresent(optional ->
generatedValues.addAll(optional.getGeneratedValues()));
currentResultSet =
driverExecutorFacade.executeQuery(usedDatabase,
metaData, queryContext, this, columnLabelAndIndexMap,
(StatementAddCallback<PreparedStatement>) this::addStatements, this::replay);
if (currentResultSet instanceof ShardingSphereResultSet) {
columnLabelAndIndexMap = ((ShardingSphereResultSet)
currentResultSet).getColumnLabelAndIndexMap();
}
return currentResultSet;
// CHECKSTYLE:OFF
} catch (final RuntimeException | SQLException ex) {
// CHECKSTYLE:ON
handleExceptionInTransaction(connection, metaData);
throw SQLExceptionTransformEngine.toSQLException(ex,
usedDatabase.getProtocolType());
} finally {
executeBatchExecutor.clear();
clearParameters();
}
}
```
I have temporarily modified the source code snippet to the following part,
which has temporarily solved my problem. However, I haven't thoroughly studied
your design logic and am not sure if this will bring more hidden dangers.
<img width="2122" height="690" alt="Image"
src="https://github.com/user-attachments/assets/8fc9692f-533b-43b1-aedf-a9b2c1d857fd"
/>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail:
[email protected]
For queries about this service, please contact Infrastructure at:
[email protected]