ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA에서 신규 엔티티 처리: EntityManager.persist()와 JpaRepository.save()의 차이점 파악하기
    JPA 2024. 4. 30. 22:08

    동일한 신규 Entity를 생성하여 EntityManager.persist()JpaRepository.save()를 통해 영속화 시켰을 때의 동작과 결과가 다를 때가 있다. 이에 대해 알아보자.

    EntityManager.persist()

    persist()를 호출할 때 전달된 엔티티 인스턴스 자체가 영속 상태가 되어 변화를 추적한다. 이 메소드는 반환값이 없으며, 저장하는 객체와 영속성 컨텍스트에 들어간 객체가 동일한 참조를 유지한다.

    EntityManager.merge()

    merge()를 호출할 때 전달된 분리된(detached) 엔티티 인스턴스의 상태를 복사하여 영속성 컨텍스트에 병합한다. 이 메소드는 새로운 영속 상태의 엔티티 인스턴스를 반환하며, 전달된 원래의 분리된 엔티티는 여전히 분리 상태로 남아 있다. 즉, merge()의 반환값이 영속성 컨텍스트에 의해 관리되는 엔티티이며, 반환된 객체만 변화를 추적한다.

    JpaRepository.save()

    save() 메소드는 내부적으로 EntityManagerpersist() 또는 merge()를 호출할 수 있다. 이 메소드의 행동은 전달된 엔티티의 상태에 따라 달라진다.

    • 신규 엔티티일 경우: 일반적으로 persist()가 호출되어 엔티티가 영속 상태가 된다.
    • 이미 존재하는 엔티티일 경우: merge()가 호출된다. merge()는 기존 엔티티의 상태를 새 엔티티의 상태로 복사하고, 그 결과로 새로운 엔티 객체를 반환한다. 이 경우, 저장하고자 했던 객체와 반환된 객체가 다른 참조를 가질 수 있다.

    차이 발생 이유

    신규 엔티티를 판단하는 기준이 중요하다. 일반적으로 Spring Data JPA의 JpaRepository.save()는 엔티티의 ID가 null이거나 0인 경우를 신규 엔티티로 간주한다. 그러나 ID의 생성 전략이 @GeneratedValue가 아니고, 로직에서 ID 값을 직접 설정하는 경우가 있다면, 이는 JpaRepository에서 신규 엔티티로 인식되지 않을 수 있다. 이 경우, JpaRepository.save()는 엔티티가 이미 존재한다고 판단하고 merge()를 호출할 가능성이 있다. 따라서, merge()를 사용하면 원본 엔티티와 반환된 엔티티가 다른 참조를 가질 수 있다.

    결론

    따라서, 같은 데이터를 저장하더라도 EntityManager.persist()는 원본 객체를 그대로 영속화하여 참조가 유지되는 반면, JpaRepository.save()는 상황에 따라 merge()를 사용하여 새 객체를 반환할 수 있어, 원본 객체와 다른 참조를 가진 객체가 반환될 수 있다. 이러한 차이를 이해하는 것은 JPA 및 Spring Data JPA를 사용하여 데이터를 효율적으로 관리하기 위해 매우 중요하다.

Designed by Tistory.