2013-04-26 4 views
0

새 항목을 유지하려고 할 때 문제가 있습니다. 나는 Eclipselink 2.4.2를 엔티티 관리자로 사용하고 있습니다. 저장소 메소드의 BaseDao 클래스는 엔티티를 새 것으로 유지 한 후에 플러시하고 새로 고칩니다 (persist-> flush-> refresh). 모든 것이 단일 트랜잭션에서 발생합니다. 나는 새로운 신뢰 개체를 만드는거야동기화 예외 동안 캐스케이드 PERSIST

TrustEntity { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "trust", cascade = {CascadeType.ALL}) 
    @PrivateOwned 
    private List<TrustIncentiveRateEntity> trustIncentiveRates; 
} 

TrustIncentiveRateEntity { 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "TRUST_ID", nullable = false) 
    private TrustEntity trust; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "trustIncentiveRate", cascade = {CascadeType.ALL}) 
    @PrivateOwned 
    private List<TrustIncentiveRateValueEntity> trustIncentiveRateValues; 
} 

TrustIncentiveRateValueEntity { 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "TRUST_INCENTIVE_RATE_ID", nullable = false) 
    private TrustIncentiveRateEntity trustIncentiveRate; 
} 

는 TrustIncentiveRateEntity을 인스턴스화하는 TrustIncentiveRateEntity 목록을 인스턴스화 거기에 하나 개의 새로운 요소를 생성 :

내 엔티티 (파트 I 우려에 대해 해요)과 같이 그 안에 하나의 새로운 요소를 만듭니다. 디버깅하는 동안 두 가지 방법으로 모든 참조가 올바른지 확인할 수있었습니다. 서버에서

로그 : 이제

, 내가 여기를 유지하려고 일어나는 것이다

FINE: SELECT SEQ_TRUST.NEXTVAL FROM DUAL 

FINE: SELECT SEQ_TRUST_INCENTIVE_RATE.NEXTVAL FROM DUAL 

FINE: SELECT SEQ_TRUST_INCENTIVE_RATE_VALUE.NEXTVAL FROM DUAL 

FINE: INSERT INTO TRUST (TRUST_ID, ACTION_DATE, ACTION_USER_ID, IS_ACTIVE, CREATION_DATE, CREATION_USER_ID, IS_INCENTIVE_ACTIVE, IS_NO_CREDIT_LIMIT, PROCESS_CURRENT_STATUS, REMARKS, STATUS_INCENTIVE, TRUST_CODE, TRUST_NAME, TRUST_TYPE, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, STRUCTURAL_ORG_UNIT_SALES_ID, STRUCTURAL_ORG_UNIT_ID, USER_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
    bind => [38007, 2013-04-26 09:46:31.582, 1003186, true, 2013-04-26 07:46:34.659, 1003186, true, false, OPEN, null, OPEN, 100058, 741963852, T, null, null, 1, 387, 387, 1003186] 

FINE: INSERT INTO TRUST_INCENTIVE_RATE (TRUST_INCENTIVE_RATE_ID, CREATION_DATE, CREATION_USER_ID, EQUIPMENT_SIZE, EXTENDED_EQ_GROUP_ID, RATE_BASIS, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, TRADE_ID, TRUST_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
    bind => [15001, 2013-04-26 07:46:39.862, 1003186, 20, 2, B, null, null, 1, 144001, 38007] 

FINE: INSERT INTO TRUST_INCENTIVE_RATE_VALUE (TRUST_INCENTIVE_RATE_VALUE_ID, CREATION_DATE, CREATION_USER_ID, EFFECTIVE_DATE, EXPIRY_DATE, INCENTIVE, STATUS, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, CURRENCY_CODE, TRUST_INCENTIVE_RATE_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
    bind => [14007, 2013-04-26 07:46:39.955, 1003186, 2013-04-26 00:00:00.0, 9999-12-31 00:00:00.0, 12, OPEN, null, null, 1, USD, 15001] 

FINE: SELECT TRUST_ID, ACTION_DATE, ACTION_USER_ID, IS_ACTIVE, CREATION_DATE, CREATION_USER_ID, IS_INCENTIVE_ACTIVE, IS_NO_CREDIT_LIMIT, PROCESS_CURRENT_STATUS, REMARKS, STATUS_INCENTIVE, TRUST_CODE, TRUST_NAME, TRUST_TYPE, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, STRUCTURAL_ORG_UNIT_SALES_ID, STRUCTURAL_ORG_UNIT_ID, USER_ID FROM TRUST WHERE (TRUST_ID = ?) 
    bind => [38007] 

FINE: SELECT TRUST_INCENTIVE_RATE_ID, CREATION_DATE, CREATION_USER_ID, EQUIPMENT_SIZE, EXTENDED_EQ_GROUP_ID, RATE_BASIS, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, TRADE_ID, TRUST_ID FROM TRUST_INCENTIVE_RATE WHERE (TRUST_ID = ?) 
    bind => [38007] 

FINE: SELECT TRUST_INCENTIVE_RATE_VALUE_ID, CREATION_DATE, CREATION_USER_ID, EFFECTIVE_DATE, EXPIRY_DATE, INCENTIVE, STATUS, UPDATE_DATE, UPDATE_USER_ID, VERSION_OPT_LOCK, CURRENCY_CODE, TRUST_INCENTIVE_RATE_ID FROM TRUST_INCENTIVE_RATE_VALUE WHERE (TRUST_INCENTIVE_RATE_ID = ?) 
    bind => [15001] 

를 지금까지 너무 좋아하지만, 트랜잭션이 EntityManager에 의해 최선을 다하고 때 나는 다음과 같은 예외가 다음 EM 실제로 TrustIncentiveRateEntity 전에 TrustIncentiveRateValueEntity를 저장하려고하고 TrustIncen을 볼 수 없습니다처럼 나를 위해, 이상한 것 같다

WARNING: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: [email protected] 
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:303) 
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:706) 
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1498) 
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3151) 
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:345) 
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:158) 
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68) 
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:435) 
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:855) 
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5136) 
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901) 
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045) 
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994) 
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222) 
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88) 
at $Proxy241.save(Unknown Source) 

tiveRateEntity. 유사한 스레드를보고 TrustIncentiveRateValueEntity 클래스의 trustIncentiveRate 필드를 통해 @ManyToOne 주석에 CascadeType.PERSIST를 추가했습니다. 그런 다음 상황은 다음과 같습니다. EM은 이전 엔티티를 삽입 한 후 SEQ_TRUST_INCENTIVE_RATE에서 nextval을 가져오고 TrustIncentiveRateValueEntity를 다시 삽입하려고 시도합니다 (새 ID로, 나머지 필드 값은 동일하게 유지됨). 이 테이블 열 중 일부의 횡단면에 고유 한 구속 조건이 있으므로 위반이 제한됩니다. 예외, 트랜잭션 롤백, 나는 아직도 슬프다. BaseDao 클래스의

내 저장 방법 :

@TransactionAttribute(TransactionAttributeType.MANDATORY) 
public T_ENTITY store(T_ENTITY entity) { 
    if (!entity.isNewlyCreated()) { 
     T_ENTITY mergedEntity = em.merge(entity); 
     flush(); 
     return mergedEntity; 
    } else { 
     try { 
      em.persist(entity); 
      flush(); 
      refresh(); 
     } catch (RuntimeException exc) { 
      entity.resetPersistentFlag(); 
      throw exc; 
     } 
     return entity; 
    } 
} 

그러나 세척하지 않고 직접 em.persist (법인), 전화/새로 고침이 같은 문제가 발생합니다.

는 서비스 호출의 논리 :

@Override 
@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public TrustEntity save(TrustEntity dto) { 
    TrustEntity trust = trustDao.store(trust); 

    workflowConversation.triggerWorkflow(); // doesn't do anything to any of the entities when they are freshly created 

    return trust; 
} 

아무도이 문제가 될 수있는 것을 식별 나를 도울 수 있을까?

+0

당신이 폭포가 TrustIncentiveRateValueEntity.trustIncentiveRate 관계에 계속 추가 할 때 중복 TrustIncentiveRateEntity을 받고 있다면, 그것은 개체 트리에서 두 개의 서로 다른 TrustIncentiveRateEntity 인스턴스가있는 것을 의미한다. 디버깅에서 이들이 동일한 지 어떻게 확인하고 있습니까? 참조를 변경할 수있는 엔티티에서 이벤트를 가져 오거나 가져 오거나 설정하는 방법이 있습니까? 예를 들어, 당신이 속성 접근을 사용하고 JPA가 사용해야하는 set 메소드에서 백 포인터를 설정하기 위해 비즈니스 로직을 포함하는 경우. – Chris

답변

0

mappedby를 양방향으로 사용하고 joincolumn을 단방향으로 표시하는 OneToMany를 사용할 수 없습니다. 충돌하여 문제를 일으키고 있습니다.

관계를 mappedby로 표시하면 관계의 모든 정보와 제어가 다른쪽에 있음을 지정합니다. 여기에는 joincolumn 정보가 포함됩니다. 시도 :

TrustEntity { 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "trust", cascade = {CascadeType.ALL}) 
    @PrivateOwned 
    private List<TrustIncentiveRateEntity> trustIncentiveRates; 
} 

TrustIncentiveRateEntity { 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "TRUST_ID", nullable = false) 
    private TrustEntity trust; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "trustIncentiveRate", cascade = {CascadeType.ALL}) 
    @PrivateOwned 
    private List<TrustIncentiveRateValueEntity> trustIncentiveRateValues; 
} 
+0

고마워, 나는 이미 나 자신도 이것을 발견했다. 그러나 불행하게도 이것은 나의 문제를 해결하지 못한다. 나는 여전히 같은 예외를 받는다. –

+0

그런 다음 질문을 수정하십시오. 생략 한 세부 정보 중 하나에 문제가 있으므로 추가 정보를 표시해야합니다. 예를 들어, 당신은 계속 언급하고, 로그는 삽입을 보여 주지만, 나무를 가로 지르는 선택을 보여줍니다. 이 선택 사항이 발생하는 방법과 이유 및 트랜잭션과의 관계를 보여주지는 않습니다. 단지 플러시 일 경우 트랜잭션이 커밋되기 전에 변경된 내용과 그 밖의 내용은 무엇입니까? 이 오류는 지속성 때문에 발생하는 것이 아니므로 로그에 이미 보존 된 것으로 표시됩니다. 트리에 남아 있지 않은 개체를 발견하고 있습니다. – Chris

+0

나는이 질문에 대한 제안 된 변경을했다. 선택에 관해서는 - 나는 그들이 새로 고침에서 온 줄 알았는데(); –