java和postgresql:重复键值违规,尽管没有发送重复键

时间:2016-08-02 12:23:37

标签: java postgresql constraints primary-key sql-insert

从我推断的内容来看,我似乎试图在我的postgresql数据库中插入一个新行,并使用新的主键组合。然而它抱怨我多次插入相同的键。

证据(来自错误日志):

ERROR com.saxo.read.postgres.RequestLoggingStore - Unable to insert request correctly, uri: /someUrlHere, uuid: a7813f97-7c0d-4739-b20b-a2a6ab2f32a3, at: 1470137399294243
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "requestlogging_pkey"
  Detail: Key (id, "timestamp")=(a7813f97-7c0d-4739-b20b-a2a6ab2f32a3, 1470137399294243) already exists.
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
        ....
ERROR com.saxo.read.postgres.RequestLoggingStore - Unable to insert request correctly, uri: /someUrlHere, uuid: 1891dc28-64b8-4a16-8d22-67af6a605aa0, at: 1470137399293662
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "requestlogging_pkey"
  Detail: Key (id, "timestamp")=(a7813f97-7c0d-4739-b20b-a2a6ab2f32a3, 1470137399294243) already exists.
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
        ....

正如你所看到的,PQSL抱怨我有一个重复的密钥违规,在它应该认为,如果我已经给它它抱怨的值。 (a7813f97-7c0d-4739-b20b-a2a6ab2f32a3, 1470137399294243)是重复的密钥。但是,从我在RequestLoggingStore中的错误日志中可以看出,报告的uuid和时间戳与PSQL报告的不同,并且不是重复键。

我立即假设我在代码中犯了一个错误,并且报告的UUID和时间戳不是我插入postgresql数据库的内容。但我不知道下面的代码是如何实现的:

public String put(String uri, String method, String body, String headers, String userId) {
        String uuid = null;
        long timestamp = stamper.timestamp();
        try {
            uuid = java.util.UUID.randomUUID().toString();

            insertQuery.setString(1, uri);
            insertQuery.setString(2, body);
            insertQuery.setString(3, method);
            insertQuery.setString(4, headers);
            insertQuery.setString(5, userId);
            insertQuery.setLong(6, timestamp);
            insertQuery.setString(7, uuid);

            insertQuery.execute();
            return uuid;
        } catch (Exception e) {
            logger.error("Unable to insert request correctly, uri: {}, uuid: {}, at: {}", uri, uuid, timestamp, e);
            return null;
        }
    }

以防您想要查看插入查询:

insertQuery = postgresConnection.prepareStatement("INSERT INTO "+TableName+"( "+listOfArgs+" ) VALUES ( ?, ?, ?, ?, ?, ?, ? );");

UUID应该为null,或者与我的错误记录器报告的值相同,是否正确?

2?

之间怎么会有区别?

我犯了错误或者psql的java驱动程序有什么问题吗?

我正在将所有传入的请求记录到我的Web服务/ API。测试时似乎工作正常。在高负荷下是否会变得太紧张?

1 个答案:

答案 0 :(得分:2)

由于insertQuery是一个类字段,因此可以在两个线程中调用方法put并覆盖相同的唯一SQL字段。因此,执行"相同"尝试记录(insertQuery)。

最好的方法是将所有变量保存在局部变量中,然后尝试使用资源。

(也可以将密钥生成留给数据库,并查询PreparedStatement.getGeneratedKeys()。)