我正在使用Postgres9.3、Spring和Java。
对于来自javadoc的BatchUpdateException:
在批处理更新中的命令无法正确执行并且抛出BatchUpdateException之后,驱动程序可能继续处理批处理中的其余命令,也可能不继续处理。如果驱动程序在失败后继续处理,则方法BatchUpdateException.getUpdateCounts返回的数组将对批处理中的每个命令都有一个元素,而不是仅对错误前成功执行的命令有一个元素。在驱动程序继续处理命令的情况下,任何失败命令的数组元素都是Statement.EXECUTE_FAILED
jdbcTemplate中的I注册跟踪转换器

public class DuplicateRecordSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {

    @Override
    protected DataAccessException doTranslate(String task, String sql, SQLException ex) {
        String errorCode = ex.getErrorCode() == 0 ? ex.getSQLState() : String.valueOf(ex.getErrorCode());

        if (ex instanceof BatchUpdateException) {
            int[] updatesCount = ((BatchUpdateException) ex).getUpdateCounts();

然后在场景中,我试图将一个批插入100个条目的数据库,但其中50个条目是重复的。最终,我无法检索第一个事务中的所有重复条目,因为返回的updateCounts始终为1。

最佳答案

你到底想要什么还不清楚。PostgreSQL Documentation显示了如何编写一个PL/PGSQL函数的例子,该函数根据主键是否已经存在而进行更新或插入。

CREATE TABLE db (a INT PRIMARY KEY, b TEXT);

CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
    LOOP
        -- first try to update the key
        UPDATE db SET b = data WHERE a = key;
        IF found THEN
            RETURN;
        END IF;
        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO db(a,b) VALUES (key, data);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- Do nothing, and loop to try the UPDATE again.
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');

因此,在您的情况下,您可以使用此函数或修改它以满足您的需要,然后进行成批的函数调用。这是我能想到的在PostgreSQL中做你想做的最有效的方法。(其他数据库具有更直接处理此问题的SQL扩展。)
相反,如果您希望插入在重复的键上失败,并且只想知道哪个成功,哪个失败,则可以重写函数以返回成功或失败布尔值,或者成功时返回null,失败时返回键ID。

关于java - BatchUpdateException updateCounts始终为1,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24776129/

10-10 02:25