JPA EclipseLink @ElementCollection未正确更新

时间:2012-02-23 23:14:57

标签: jpa eclipselink

将EclipseLink 2.3.2与针对OracleXE的静态编织(Maven插件)结合使用。

我有以下实体

@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

我不知道设置中有什么问题 - 我正在使用flyway来执行我手工编写的SQL / DDL。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

根据EclipseLink如何处理ElementCollection(order)的元素,您不能拥有连接列和订单列的主键。 EclipseLink确实使用可能包含或不包含序列列的SQL正确处理更新,但顺序是这样的,即在事务中同一时间可以存在相同的LIST_ID,SEQ组合。

删除主键,一切正常。