0
將EclipseLink 2.3.2與靜態編織(Maven插件)一起用於OracleXE。JPA EclipseLink @ElementCollection未正確更新
我有以下實體
@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;
}
,當我做更新內容如下:
// 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();
我得到一個重複鍵錯誤 - 就像它沒有刪除舊數據
> 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
我不知道什麼是錯誤的設置 - 我使用飛橋執行SQL/DDL我手寫的。任何幫助表示讚賞。
你對集合表中的主鍵使用了什麼?約束是說pk約束被違反了,所以檢查你是否已經適當地設置了它 - 即你不只是使用LIST_ID作爲pk,因爲同一個列表中的兩個元素將使用相同的LIST_ID。要麼不爲該表設置pk,要麼使用像SEQ和LIST_ID這樣獨特的東西。如果不是這種情況,請嘗試打開參數日誌記錄來查看正在使用的內容,方法是將「eclipselink.logging.parameters」屬性設置爲true。 – Chris 2012-02-24 15:34:19
是的 - PK是(list_id,seq) - 感謝您的日誌提示。當我調試它時,我可以看到DirectCollectionMapping有7個更改 - 4個插入,然後3個刪除(測試用例用4替換3個值) - 然後按順序檢查更改列表 - 首先執行插入操作。 – 2012-02-24 16:43:48
用H2試過我的測試並讓EclipseLink生成模式。查看生成的模式,EclipseLink創建沒有主鍵的表,以便插入然後刪除,但刪除list_id和內容上的匹配。如果我使用共享值更新列表,那麼hella錯誤。 – 2012-02-24 17:38:10