我正在使用Spring JDBCTemplate和BatchPreparedStatementSetter批量更新postgreSQL数据库。 我想捕获错误的记录,经过一些文章的研究后,发现捕获BatchUpdateException并查找'Statement.EXECUTE_FAILED'可以帮助我识别错误的记录。 但是,当我按照以下方式实现时,从未收到batchUpdate异常。
这里,我尝试重复输入相同的id“120”,以便在数据库级别上强制唯一约束违规,从而引发异常。
@Override
@Transactional
public void batchInsertTenantPayloads(List<Payload> payloadMessages) {
try {
jdbcTemplate.batchUpdate(DBQueryConstants.INSERT_INTO_MESSAGE_METERING_PAYLOAD, new BatchPreparedStatementSetter() {
@Override
public int getBatchSize() {
return payloadMessages.size();
}
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setLong(1, 120);
ps.setString(2, payloadMessages.get(i).getId());
ps.setDate(3, Date.valueOf(payloadMessages.get(i).getTs().toLocalDate()));
ps.setString(4, payloadMessages.get(i).getContent().getId());
ps.setInt(5, payloadMessages.get(i).getStatus().ordinal());
ps.setString(6, MyUtils.toJSON(payloadMessages.get(i)));
}
});
} catch (Exception e) {
if (e.getCause() instanceof BatchUpdateException) {
LOGGER.info("Batch exception occurred");
BatchUpdateException be = (BatchUpdateException) e.getCause();
int[] batchUpdateCounts = be.getUpdateCounts();
for (int index = 0; index < batchUpdateCounts.length; index++) {
if (batchUpdateCounts[index] == Statement.EXECUTE_FAILED) {
LOGGER.error(
"[MMC] batch update Error execution >>>>>>>>>>>" + index + " --- , codeFail : " + batchUpdateCounts[index]
+ "---, line " + payloadMessages.get(index));
}
}
}
}
}
挑战在于我从未进入BatchUpdateException块。相反,我得到了一个
org.springframework.dao.DuplicateKeyException
嵌套异常是
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "message_metering_payload_pkey"
我该怎么做才能捕获batchUpdate异常并只获取错误行并提交好的行。
我的批量大小为500。PostgreSQL版本为9.6,我使用的是spring 2.0和spring jdbc 5.1.3。
堆栈跟踪看起来像这样
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [insert into message_metering_payload(id,tenant_name,source_dt,exchange_id,status,payload)values(?,?,?,?,?,?)]; ERROR: duplicate key value violates unique constraint "message_metering_payload_pkey"
Detail: Key (id)=(120) already exists.; nested exception is org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "message_metering_payload_pkey"
Detail: Key (id)=(120) already exists.
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:242)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1444)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:632)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:646)
at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:936)
on conflict do nothing
对你来说不是一个选项吗? - Denis Zavedeev