티스토리 뷰

반응형

JPA를 통한 테스트 구현 과정에서 entityManager의 merge()를 사용해 준영속인 엔티티를 다시 영속화하고 변경 감지를 아래처럼 사용하려 했으나 제대로 적용되지 않았다.

 

        entityManager.merge(entity);
        entity.proceed(); // 상태 변경 메서드
        entityManager.flush();

 

준영속 상태인 엔티티를 다시 영속화하고 상태를 변경하였는데 변경 감지가 동작하지 않았다.

merge() 시에 select 쿼리가 나가기는 하나 proceed() 시에 update 쿼리가 나가지는 않았다.

proceed() 이후 entityManager.contains(entity)로 영속화 여부를 확인해도 false가 출력되었다.

 

 

아래와 같이 순서를 바꾸니 변경 내용을 정상적으로 update했다.

 

        entity.proceed();
        entityManager.merge(entity);
        entityManager.flush();

 

엔티티의 상태를 변경한 뒤 merge()를 호출하니 select와 update 쿼리가 연속하여 나가는 것을 확인했다.

 

 

 

이유가 무엇일지 한참 고민하다가 답을 찾았다.

java.persistence의 EntityManager의 JavaDoc에는 그런 내용이 없는 줄 알았는데

 

 

자세히 읽어보니 merge()의 파라미터로 넘어온 entity 자체는 영속성 컨텍스트로 관리되는지에 대한 내용은 없고

반환된 엔티티 merge()는 명확히 관리되는 entity임을 명시하고 있다.

 

JPA 구현체에 따라 다를 순 있겠지만 merge()가 반환하는 엔티티를 사용해야 변경 감지가 확실히 될 듯하다.

 

 

수정하여 아래의 코드로 확인해 보니 변경 감지가 잘 된다.

        Entity entity = entityManager.merge(entity);
        entity.proceed();
        entityManager.flush();

 

 

참고로 <Java ORM 표준 JPA 프로그래밍>에서도 다음의 내용을 찾을 수 있었다. (118pg)

merge()는 파라미터로 넘어온 준영속 엔티티를 사용해서 새롭게 병합된 영속 상태의 엔티티를 반환한다. 파라미터로 넘어온 엔티티는 병합 후에도 준영속 상태로 남아 있다.

 

결론

merge()의 파라미터로 넘기는 준영속 엔티티가 영속화되는 것이 아니다.

merge()의 반환 엔티티가 영속성 컨텍스트에서 관리되는 엔티티다.

 


Spring Data JPA를 많이 쓰다 보니 직접 entityManager의 호출은 테스트 구현에서나 종종 해 덕분에 세부 동작을 상기하게 된다.

반응형