我正在使用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/