2016-10-29 3 views
2

저는 (Eclipselink를 사용하여) 그렇게 기대하지 않은 JPA 동작에 당황합니다.커밋되지 않은 JPA find() 메소드를 읽지 않은 이유는 무엇입니까?

나는 Stateless 세션 EJB (3.2) 인 Wildfly 10 (JDK-8)에서 실행됩니다. 내 메서드 호출은 - 기본적으로 - 트랜잭션에 캡슐화됩니다. 엔터티 빈을 읽고 업데이트 할 때 비즈니스 방법으로 업데이트, 특히 엔터티의 버전 번호를 인식하지 못했습니다. 그래서

org.eclipse.persistence.exceptions.OptimisticLockException 

내 코드에서 내 전화의 결과는이 같은 단순화 된 모양 : 나는

주석 방법에 (엔티티 빈의 데이터를 변경하고 플러시) 코드를 넣으면

public ItemCollection process(MyData workitem) { 

    .... 
    // load document from jpa 
    persistedDocument = manager.find(Document.class, id); 
    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 3 

    // change some data 
    .... 
    manager.flush(); 
    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 4 

    .... 
    // load document from jpa once again 
    persistedDocument = manager.find(Document.class, id); 

    logger.info("@version=" + persistedDocument.getVersion()); 
    // prints e.g. 3 (!!) 

    // change some data 
    .... 
    manager.flush(); 
    // Throws OptimisticLockException !! 
    // [email protected]] cannot be updated because it has changed or been deleted since it was last read 

    ... 
} 

@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW) 

모든 것이 예상대로 작동합니다.

하지만 내 코드에서 find() 메서드의 두 번째 호출이 새 버전 번호를 읽지 않는 이유는 무엇입니까? 나는 flush()와 find() 호출 후에 버전 4를 기대할 것이다.

+0

두 번째 동일한 트랜잭션에서 호출 하시겠습니까? –

+0

예 이것들은 모두 하나의 동일한 상태 저장 세션 EJB 메소드 – Ralph

+0

에서 실행됩니다. 다른 프로젝트에서 비슷한 코드를 사용했다고 생각합니다.하지만 OneToMany 관계가 많습니다. 지금과 다른 동작이있는 것 같습니다. – Ralph

답변

2

는 결국은

manager.clear(); 

이 문제를 해결 호출하는 것 같습니다. 나는 객체를 분리하는 것이 똑같이해야한다고 생각했지만, 나의 경우에는 clear()를 호출하면 문제가 해결되었다.

더 많은 연구 결과 :

는 결국이 방법은 분리 전화()와 플러시() 서비스 층을 형성하는 좋은 생각되지 않을 것 같습니다. 이 ID를 클라이언트에 반환하기 전에 비즈니스 메서드를 떠나기 전에 내 엔터티의 새 버전 ID를 얻으려고했기 때문에이 작업을 수행했습니다. 이 경우 내 전략을 변경했고 엔티티 콩을 분리하고 플러시하는 것으로 모든 '나쁜 물건'을 제거했습니다. 코드가 더 명확 해지고 결국 코드 복잡성이 크게 줄어 들었습니다.

물론 entityManager가 올바르게 작동합니다. 한 트랜잭션에서 동일한 엔티티 bean을 여러 번 다시 조회하면 entityManager는 올바른 갱신 된 버전을 리턴합니다.

그래서 내 자신의 질문에 대한 대답은 : flush() 및 clear() 메소드를 그대로 놔두고 사용하는 좋은 이유가 없다는 것입니다.