2012-06-12 3 views
13

EclipseLink 2.3.0을 사용하고 있습니다. 나는 다음과 같습니다 (따라서 컨테이너, 아니 JTA의 외부) 단위 테스트에서 전화 오전 방법이 있습니다 변경은이에 데이터베이스에 유지하고,보고되지 않고 있었다JPA/EclipseLink : EntityManager.getTransaction()이 새 트랜잭션을 만들거나 활성 트랜잭션을 반환합니까?

EntityManager em = /* get an entity manager */; 
em.getTransaction().begin(); 
// make some changes 
em.getTransaction().commit(); 

오랜 시간 마침내 EntityManager.getTransaction()이 두 호출에서 모두 동일한 EntityTransaction이 아니라 실제로 새로운 EntityTransaction을 반환한다는 것을 알게되었습니다. 첫 번째 호출은 새 트랜잭션을 만들고 시작하고 두 번째 호출은 다른 트랜잭션을 만들고 커밋합니다. 첫 번째 트랜잭션은 커밋되지 않았으므로 변경 내용은 저장되지 않습니다.

log.info(em.getTransaction().toString()); 
log.info(em.getTransaction().toString()); 

이 로그 메시지의 결과 어떤 :

INFO: org.ecl[email protected]1e34f445 
INFO: org.ecl[email protected]706a4d1a 

두 개의 서로 다른 개체 ID의가 있다는 것을 확인하는 두 가지 경우 우리는 다음과 같이이 문제를 확인했습니다. 이에 코드를 변경 :

EntityManager em = /* get an entity manager */; 
EntityTransaction tx = em.getTransaction(); 
tx.begin(); 
// make some changes 
tx.commit(); 

을 ... 문제를 해결할. 이제 코드를 실행할 때 데이터베이스 작업을 수행하기 위해 생성 된 SQL 문을보고 데이터베이스를보고 데이터가 변경되었습니다.

트랜잭션 관리에 사용되는 코드를 권장하는 수많은 코드 예제를 온라인 (JPA와 일반적으로 EclipseLink의 경우)에서 보았 기 때문에이 결과에 조금 놀랐습니다. 나는 특별히 이것에 대한 정보를 찾기 위해 광범위하게 수색했지만 아무 것도 발견하지 못했습니다. 무슨 일 이니?

JPA 스펙에서 getTransaction()이 수행하는 것과 트랜잭션이 새 것이거나 동일하지 않은 것이 정확히 무엇인지 지정했습니다. 이것을 제어하는 ​​persistence.xml에 설정이 있습니까? 행동은 JPA 스펙의 각 구현에 따라 다릅니 까?

모든 정보 또는 안내에 대해 감사드립니다.

답변

1

JPA 스펙 (7.5.4 절 참조)에는 getTransaction()을 사용하여 트랜잭션을 시작하고 커밋하는 방법을 보여주는 예제가 명시되어 있습니다. 코드가 잘되어야합니다.

테스트 결과 두 개의 서로 다른 개체가 있다는 것을 보여 주지만 동일한 트랜잭션이 사용되지는 않습니다. 어쩌면 반환 된 객체는 실제의 단일 트랜잭션 객체에 대한 프록시 일뿐입니다.

트랜잭션이 // make some changes 아래 숨겨진 코드 내에서 커밋되거나 롤백 된 것일 수 있습니다.

+1

내가 게시해야하는 코드가 더 효과적 일 수 있습니다. 나는 그 질문을 명확히하기 위해 편집했다. –

+0

그 점을 이해합니다. 나의 요점은 * JPA 스펙이 트랜잭션을 시작하고 커밋하는데'em.getTransaction()'이 사용되는 코드 샘플을 포함하고 있기 때문에 * 작동해야한다는 것이다. 그래서 내가 말했듯이, begin과 commit 사이의 코드는 이미 트랜잭션을 커밋하거나 롤백하지 않는 한, EclipseLink의 버그 여야합니다. 내 대답은 문제에 대한 해결책이 아니라 코드가 작동해야한다는 확인입니다. EclipseLink에 버그를 제출하는 것이 좋습니다. –

5

getTransaction() 사용은 JPA와 EclipseLink에서 작동합니다 (이것이 우리 자신의 테스트 작동 방식입니다).

제 생각에 당신은 다른 이상한 일을하고 계십니다.

스프링 또는 다른 레이어를 사용하고 있습니까? 테스트를 위해 전체 코드 및 persistence.xml을 포함하십시오. persistence.xml에서 JTA를 사용하고 있지 않은지 확인하십시오.

+0

getTransaction()은 JTA 엔터티 관리자에서 호출 될 경우 IllegalStateException을 던져야합니다. –

+0

봄이 아니며 JTA가 없습니다. 이것은 컨테이너 외부의 JUnit 테스트에서 호출됩니다. "make some changes"의 코드는 4 줄이며, 새 객체를 만들고, 정수 값을 설정하고, 병합하고 플러시합니다. 내가 분이되면 증류 된 예제를 만들 것이다. 아마도 이것은 EclipseLink 버그 일 것입니다. –

0

persist before commit:을 사용해 보셨습니까?

Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher"); 
    em.getTransaction().begin(); 
    em.persist(employee); 
    em.getTransaction().commit(); 
관련 문제