Using EclipseLink 2.3.2 with static weaving (Maven plugin) against OracleXE.
I have the following Entity
@Entity
@Table(name="LIST")
public class List {
...Id...
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "LIST_CONTENTS", joinColumns = @JoinColumn(name = "LIST_ID"))
@OrderColumn(name = "SEQ")
@Column(name = "CONTENT", length = 4000)
private java.util.List<String> contents;
}
and when I update the contents by doing the following:
// newContents is a String[]
em.getTransaction().begin();
List list = em.find(List.class,id);
list.setContents(new ArrayList<String>(Arrays.asList(newContents)));
em.getTransaction().commit();
I get a duplicate key error – like it didn’t delete the old data
> Error Code: 1 Call: INSERT INTO NIBR_LIST_CONTENTS (LIST_ID, CONTENT,
> SEQ) VALUES (?, ?, ?)
> bind => [3 parameters bound] Query: DataModifyQuery(sql="INSERT INTO NIBR_LIST_CONTENTS (LIST_ID, CONTENT,
> SEQ) VALUES (?, ?, ?)")
> at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
> at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
> at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)
> ... 54 more Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):
> org.eclipse.persistence.exceptions.DatabaseException Internal
> Exception: java.sql.SQLIntegrityConstraintViolationException:
> ORA-00001: unique constraint (ANNEX.NIBR_LIST_CONTENTS_PK) violated
>
> Error Code: 1 Call: INSERT INTO NIBR_LIST_CONTENTS (LIST_ID, CONTENT,
> SEQ) VALUES (?, ?, ?)
> bind => [3 parameters bound] Query: DataModifyQuery(sql="INSERT INTO NIBR_LIST_CONTENTS (LIST_ID, CONTENT,
> SEQ) VALUES (?, ?, ?)")
> at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
> at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:840)
> at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
> at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
> at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
> at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1717)
> at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:253)
> at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
> at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
> at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:236)
> at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:216)
> at org.eclipse.persistence.internal.queries.StatementQueryMechanism.executeNoSelect(StatementQueryMechanism.java:115)
> at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85)
> at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:844)
> at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:743)
> at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2871)
> at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)
> at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)
> at org.eclipse.persistence.mappings.DirectCollectionMapping.performDataModificationEvent(DirectCollectionMapping.java:2080)
> at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:157)
> at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3799)
> at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1415)
> at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:636)
> at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1505)
> at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:267)
> at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1143)
> at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
> ... 56 more Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique
> constraint (ANNEX.NIBR_LIST_CONTENTS_PK) violated
>
> at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
> at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
> at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
> at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
> at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
> at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
> at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
> at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)
> at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
> at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
> at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3657)
> at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350)
> at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:831)
> ... 81 more
I’ve no idea what’s wrong in the setup – I am using flyway to execute the SQL/DDL that I’ve written by hand. Any help is appreciated.
Based on how EclipseLink processes the elements of the ElementCollection (order), you cannot have a primary key of the join columns and the order column. EclipseLink does handle updates properly with SQL that may or may not include the sequence column, but the order is such that the same LIST_ID, SEQ combination can exist for the same time in the transaction.
Remove the primary key and it all works.