2012-02-23 2 views
0

Использование EclipseLink 2.3.2 со статическим плетением (плагин Maven) против OracleXE.JPA EclipseLink @ElementCollection не обновляется должным образом

У меня есть следующие 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; 

} 

и когда я обновить содержимое, выполнив следующие действия:

// 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, что Я написал от руки. Любая помощь приветствуется.

+0

Что вы использовали для первичного ключа в таблице сбора? Ограничение означает, что ограничение pk нарушено, поэтому убедитесь, что вы настроили его соответствующим образом - то есть, что вы не просто используете LIST_ID как pk, так как два элемента в одном списке будут использовать тот же LIST_ID. Либо не устанавливайте pk для таблицы, либо используйте что-то уникальное, как SEQ и LIST_ID. Если это не так, попробуйте включить ведение журнала параметров, чтобы узнать, что используется, установив для свойства eclipselink.logging.parameters значение true. – Chris

+0

Yep - pk is (list_id, seq) - спасибо за подсказку при регистрации. Когда я его отлаживаю, я вижу, что DirectCollectionMapping имеет 7 изменений - 4 вставки, а затем 3 удаления (тестовый сценарий заменяет 3 значения на 4) - затем он перебирает список изменений в порядке - сначала выполняет вставку. –

+0

Пробовал мой тест с H2 и позволил EclipseLink генерировать схему. Посмотрел результирующую схему, и EclipseLink создает таблицу без первичного ключа, чтобы она могла вставлять и удалять, но удаляет совпадения в list_id и содержимом. Это неверно, если я обновляю список с общим значением. –

ответ

0

Основываясь на том, как EclipseLink обрабатывает элементы ElementCollection (order), вы не можете иметь первичный ключ столбцов соединения и столбец заказа. EclipseLink корректно обрабатывает обновления с помощью SQL, который может включать или не включать столбец последовательности, но порядок таков, что одна и та же комбинация LIST_ID, SEQ может существовать в одно и то же время в транзакции.

Удалить первичный ключ, и все это сработает.

Смежные вопросы