2012-10-31 5 views
0

저는 Spring의 트랜잭션 지원과 JPA (Hibernate)를 사용하여 엔티티를 유지합니다. 모든 것이 제대로 작동하지만 한 요청 내에서 부분 업데이트를 처리 할 때 막혔습니다.Spring 관리 트랜잭션 내의 JPA EntityManager 두 개?

모든 사용자 (HTTP) 요청에 대해 데이터베이스 항목에 로그 항목을 기록했습니다. "기본"비즈니스 엔티티가 실패합니다 (예 : 유효성 검증 오류로 인해). 따라서 첫 번째/주 트랜잭션은 롤백되지만 두 번째 (로그 작성)는 커밋해야합니다. 이 로그 항목을 작성하기위한 올바른 전파 레벨을 사용하여 작동하는 것 같다 :

@Repository 
@Transactional(propagation = Propagation.REQUIRES_NEW) 
public class UserTracker extends ... { 

    @PersistenceContext private EntityManager em; 

    public void log(...) { 
    // create log entity and persist it 
    ... 
    em.persist(log); 
    em.flush(); 
    } 

} 

내 문제는 내가 처음과 두 번째 트랜잭션에 주입 같은 EntityManager를 얻을 수 있다는 점이다. 따라서 엔티티 관리자를 플러시 (두 번째 트랜잭션이 커밋 될 때 명시 적으로 또는 암시 적으로)하면 첫 번째 트랜잭션에서 내 더러운 비즈니스 엔터티를 플러시합니다.

어떻게 해결할 수 있습니까? 로깅 부분에 두 번째 깨끗하고 신선한 EntityManager를 사용하고 싶습니다. 프로그램 적으로 하나를 열 수 있다는 것을 알았지 만, 이것을하기위한 클리너/선언적 "Spring-way"가 있습니까?

편집 :

내 두 번째 트랜잭션이 내 주요 비즈니스 트랜잭션 내에 중첩 된 것으로, 사실에서 줄기 수있는 내 문제 : 나는 두 개의 트랜잭션을 직렬화 내 문제를 해결했습니다

|-------------- A --------------X <- Rollback of main business transaction (A) 
        |--- B ---|  <- Commit of second log transaction (B) 

:

|--------- A --------X |--- B ---| 

이제 모든 것이 좋지만 호기심에서 벗어났습니다. 첫 번째 접근 방식을 고수한다면 제안 된대로 JDBC에 의지하지 마십시오. 두 번째 (중첩 된) 트랜잭션에 대한 엔티티 관리자를 구성하여 새로운 트랜잭션에 대해 새 트랜잭션을 얻을 수있는 방법은 무엇입니까? 이 작업을 수행 할 수 있습니까?

답변

-1

로깅 코드와 비즈니스 로직 코드에 REQUIRE_NEW가 있으면 문제가 발생하는 이유가 확실하지 않습니다. 내 코드에는 매우 비슷한 설정이있다. 자신이 생각하는 곳에서 거래가 시작되고 있습니까? 프록시 트랜잭션 또는 aspectJ 트랜잭션을 사용하고 있습니까?

프록시 트랜잭션을 사용하는 경우 tx가 시작되도록 프록시를주의 깊게 살펴야합니다.

당신이 할 수있는 또 다른 일은 사용자 로깅을 위해 SpringJDBC 템플릿을 사용하는 것입니다. @Repository가 EntityManager와 JDBCTemplate 모두를 사용하여 작업하는 것은 완벽하게 괜찮습니다. 같은 방법으로 그들을 혼합하지 마십시오.

+0

생각해 보면 다소 이상한 설정입니다. 로그를 작성하려고 할 때 내 주요 비즈니스 트랜잭션이 아직 열려 있습니다 (여기서는 Open-In-View 패턴을 사용하고 있습니다). 나는 부작용을 피하기 위해이 두 가지 트랜잭션을 직렬화 할 수있다. –

관련 문제