如何在postgresql中使用jdbctemplate batchupdate捕获错误记录?

tkqqtvp1  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(597)

我正在使用springjdbctemplate和batchpreparedstatementsetter对postgresql数据库执行批更新。我想捕获错误的记录,在浏览了一些帖子之后,发现捕获batchupdateexception然后查找“statement.execute\u failed”可以帮助我识别错误的记录。然而,当我按照下面的方式实现它时,我从未得到batchupdate异常。
在这里,我尝试重复输入相同的id“120”,以便获得唯一的约束冲突,从而在db级别强制执行异常。

@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:错误:重复的键值违反唯一约束“message\u metering\u payload\u pkey”
我可以采取什么不同的方法来捕获batchupdate异常,只获取错误行并提交好的行。
我的批量是500。postgre版本是9.6,我使用Spring2.0和SpringJDBC5.1.3。
stacktrace看起来像这样

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)
wtlkbnrh

wtlkbnrh1#

你不明白 BatchUpdateException ,因为您可能会使用 SQLErrorCodeSQLExceptionTranslatorjdbcTemplate ,它处理 BatchUpdateException 以一种特殊的方式:

if (sqlEx instanceof BatchUpdateException && sqlEx.getNextException() != null) {
    SQLException nestedSqlEx = sqlEx.getNextException();
    if (nestedSqlEx.getErrorCode() > 0 || nestedSqlEx.getSQLState() != null) {
        sqlEx = nestedSqlEx;
    }
}

有一个问题:
jdbctemplate.batchupdate不返回batchupdateexception的计数器
如果使用 SQLStateSQLExceptionTranslator :

jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator());

然后你会得到 BatchUpdateException 作为一个 cause :

try {
    // ...
} catch (DataAccessException e) {
    Throwable cause = e.getCause();
    logger.info("cause instanceof BatchUpdateException = {}", cause instanceof BatchUpdateException);
 }

但请注意,对于postgresqljdbc驱动程序 BatchUpdateException#getUpdateCounts() 将包含 EXECUTE_FAILED 只是,尽管某些行可以成功插入。
看到这个问题了吗

相关问题