当前位置: 首页 > 知识库问答 >
问题:

如何在postgreSql中使用JDBCTemboard BatchUpdate捕获错误记录?

万俟沛
2023-03-14

我正在使用Spring JDBCTemboard和BatchPREaredStatementSetter在postgreSql DB上执行批处理更新。我想捕获错误的记录,在浏览了一些帖子后,发现捕获BatchUpdateExctive,然后寻找“语句”。EXECUTE_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块。相反,我得到了一个

组织。springframework。刀。重复键异常

嵌套的异常是

组织。postgresql。util。PSQLException:错误:重复的键值违反了唯一约束“message_metering_payload_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)

共有1个答案

朱渝
2023-03-14

您不会得到BatchUpdateException,因为您可能会在jdbcTemplate中使用SQLErrorCodeExceptionTranslator,它以特殊方式处理BatchUpdateExceptions:

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

有一个关于它的问题:

  • jdbcTemplate.batchUpdate不返回BatchUpdateExctive的计数器

如果您使用SQLStateSQLExceptionTranslator,则可以缓解此问题:

jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator());

然后你会得到BatchUpdateExctive作为原因

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

但请注意,对于postgresql jdbc驱动程序BatchUpdateException#getUpdateCounts()将仅包含EXECUTE_FAILED,尽管某些行可以成功插入。

看到这个问题了吗

 类似资料:
  • 我正在从可能被压缩的服务器下载内容,所以我使用了我在不同地方找到的样板: 问题是,如果HTTPS请求因网络错误而失败,我有时会引发以下异常: 该“错误”事件处理程序未捕获异常。那么我如何捕获它,以便能够正确地清理文件并知道如何重试?

  • 我有下面的代码,我用它来让一个用户静默登录 如果用户无法静默登录,将会导致错误。 我遇到的问题是,我似乎无法抓住例外。捕获错误或捕获块正在被击中。如何捕获此错误?

  • 是否可以使用promises的ES6语法捕获异步错误?例如,以下操作不起作用(.catch未捕获错误): 但是这个同步版本有: 使用try/catch块和清除catch中的错误是执行以下操作的唯一解决方案吗? 对于这个问题,假设抛出错误的代码部分位于另一个命名函数中,因此它没有访问函数的权限。 谢谢 编辑:这里有一个更完整的示例,说明我想在JSFIDLE中做什么。

  • 问题内容: 我在Python中构建了一个简短的url转换器引擎,并且看到大量的“管道破损”错误,并且很好奇在使用BaseHTTPServer类时如何最好地捕获它。这不是全部代码,但可以让您大致了解我目前正在做什么: 该代码本身运行良好,但是在生产中几乎立即开始引发错误: 这些错误的大部分似乎源于在调用send_header()方法时遇到的问题,其中我要写的是: 所以我很好奇在我的代码中尝试捕获此I

  • 我正在尝试使用JavaSeleniumWebDriver捕获网页的所有javascripts错误。 下面是我的代码示例: 作为Firefox驱动程序,我使用的是这个版本:geckodriver-v0。30.0-linux64。焦油广州 以下是我的Selenium版本: 我的问题是,在运行前面的代码时,出现以下异常: 司机信息:司机。版本:组织上的RemoteWebDriver。openqa。硒。j

  • 问题内容: 我正在使用PHP函数将数据从本地计算机发布到Web服务器。我的代码如下: 不幸的是,我无法捕获任何错误,例如404、500或网络故障。那么,我如何得知数据没有发布到远程或从远程检索呢? 问题答案: 您可以使用该功能检测是否有错误。例如: