-
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()
메소드는 내부적으로EntityManager
의persist()
또는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를 사용하여 데이터를 효율적으로 관리하기 위해 매우 중요하다.'JPA' 카테고리의 다른 글
JPA Entity에 public or protected no-arg constructor가 필수인 이유 (1) 2024.10.09 JPA 연관 관계의 주인과 소유 측: 개념 및 예제 (0) 2024.05.04 JPA 연관 관계 어노테이션의 속성 분석 (0) 2024.05.04 JPA : 영속성 전이(Cascade) (0) 2024.05.02 Spring Data JPA 가이드 모음 (0) 2024.05.02 - 신규 엔티티일 경우: 일반적으로