I am using EclipseLink 2.4.2 (in combination with Spring, but I don't think it has anything to do with our issue here) and we had a few times the following exception:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001 : unique constraint (****.PK_*****) violated
Our primary keys are generated by EclipseLink which uses an Oracle sequence to allocate them. I double checked, and the allocationSize
matches exactly the increment by
defined on the sequence.
Here is an example of how this sequence is defined in our Java class:
@Id
@SequenceGenerator(name = "SOME_GENERATOR", sequenceName = "SOME_SEQ", allocationSize = 10000, initialValue = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SOME_GENERATOR")
@Column(name = "ID")
private Long id;
Here is the sequence creation SQL-statement:
CREATE SEQUENCE SOME_SEQ INCREMENT BY 10000 START WITH 10000;
Of course, the problem is hardly reproduceable and only happens randomly. It seems to happen more often when the server is under heavy load.
I don't know if this is relevant, but here are some extra infos:
My first thinking would be that this is related to concurrency, but it would seem like a rather severe issue for such a mature framework. Any other thing I should verify or that I could have overlooked?
I have looked at related posts such as theses ones:
but they don't seem to help in my case.
We eventually found an explanation to this issue.
The actual problem came from the fact that the database was reset (so drop tables and sequences, then re-initialize everything), but the application server wasn't.
Since the ids are used by multiple entities, the behaviour was rather random and collisions were actually not likely to occur.
Developers and testers will now always restart application server after a reset of the DB.