JPA和多线程合并生成异常ID已存在

时间:2015-07-09 11:10:13

标签: java multithreading postgresql jpa

我有一个实体,其中id字段被描述为:

@Id
@Column(name = "id", unique = true, nullable = false, insertable = true, updatable = true)
@SequenceGenerator(name = "records_id_seq", sequenceName = "records_id_seq", schema = "recorder", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "records_id_seq")
private Long id;

似乎当多个线程尝试插入新数据时,存在一个问题,因为我的应用程序想要插入具有相同id值的2个实体,并且我的数据库拒绝这两个实体,因为id是唯一的。

应该怎样做才能证明这一点?

是一种告诉我的实体不尝试插入id值并让数据库在插入阶段自己生成它的方法吗?

感谢您的帮助。

编辑:例外:

11:17:47.407 ERROR - Uncatched exception at 201507091117 for thread Thread[RecorderBase-Pool-Thread-1,5,RMI Runtime] : 
javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pkey_records_id"
  Détail : Key (id)=(280) already exists.
Error Code: 0
Call: INSERT INTO recorder.records (id, name, number, DELETED, frid, frname, end, start, hid, REFERENCE, toid, toname) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    bind => [12 parameters bound]
Query: InsertObjectQuery(Record[280/20014364334653801])
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:159) ~[ModuleA-2.1.0.jar:na]
    at DBHelper.save(DBHelper.java:215) ~[ModuleA-2.1.0.jar:na]
    at DBHelper.save(DBHelper.java:230) ~[ModuleA-2.1.0.jar:na]
    at RecordEngine$1.run(RecordEngine.java:253) ~[ModuleA-2.1.0.jar:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:1.8.0_40]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:1.8.0_40]
    at java.lang.Thread.run(Unknown Source) ~[na:1.8.0_40]
Caused by: org.eclipse.persistence.exceptions.DatabaseException: 
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pkey_records_id"
  Détail : Key (id)=(280) already exists.
Error Code: 0
Call: INSERT INTO recorder.records (id, name, number, DELETED, frid, frname, end, start, hid, REFERENCE, toid, toname) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    bind => [12 parameters bound]
Query: InsertObjectQuery(Record[280/20014364334653801])
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1611) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2000) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1802) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1784) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1735) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:273) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:193) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:139) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4205) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:134) ~[ModuleA-2.1.0.jar:na]
    ... 6 common frames omitted
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pkey_records_id"
  Détail : Key (id)=(280) already exists.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198) ~[ModuleA-2.1.0.jar:na]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927) ~[ModuleA-2.1.0.jar:na]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255) ~[ModuleA-2.1.0.jar:na]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561) ~[ModuleA-2.1.0.jar:na]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419) ~[ModuleA-2.1.0.jar:na]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:365) ~[ModuleA-2.1.0.jar:na]
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890) ~[ModuleA-2.1.0.jar:na]
    ... 38 common frames omitted

1 个答案:

答案 0 :(得分:0)

好的,我发现了问题。

我甚至尝试更改表模式,删除自动生成的列,因此没有序列,但仍然是具有应用程序生成值的主键。但仍有例外。

问题很容易解决:为每个线程使用新的实体管理器。

那里!没有插入异常;)

谢谢大家。