스프링 데이터 JPA 2. JpaRepository.save() 메소드 - KwangtaekJung/inflearn-spring-data-jpa-keesun GitHub Wiki
-
JpaRepository의 save()는 단순히 새 엔티티를 추가하는 메소드가 아닙니다.
- Transient 상태의 객체라면 EntityManager.persist()
- Detached 상태의 객체라면 EntityManager.merge()
-
Transient인지 Detached 인지 어떻게 판단 하는가?
- 엔티티의 @Id 프로퍼티를 찾는다. 해당 프로퍼티가 null이면 Transient 상태로 판단하고 id가 null이 아니면 Detached 상태로 판단한다.
- 엔티티가 Persistable 인터페이스를 구현하고 있다면 isNew() 메소드에 위임한다.
- JpaRepositoryFactory를 상속받는 클래스를 만들고 getEntityInfomration()을 오버라이딩해서 자신이 원하는 판단 로직을 구현할 수도 있습니다.
-
EntityManager.persist()
-
https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#persist(java.lang.Object)
-
Persist() 메소드에 넘긴 그 엔티티 객체를 Persistent 상태로 변경합니다.
-
-
EntityManager.merge()
-
https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#merge(java.lang.Object)
-
Merge() 메소드에 넘긴 그 엔티티의 복사본을 만들고, 그 복사본을 다시 Persistent 상태로 변경하고 그 복사본을 반환합니다.
-
@DataJpaTest
class PostRepositoryTest {
@Autowired
PostRepository postRepository;
@PersistenceContext
EntityManager entityManager;
@Test
public void save() {
Post post = new Post();
post.setTitle("jpa");
Post savedPost = postRepository.save(post); // persist
Assertions.assertThat(entityManager.contains(post)).isTrue();
Assertions.assertThat(entityManager.contains(savedPost)).isTrue();
Assertions.assertThat(savedPost == post);
Post postUpdate = new Post();
postUpdate.setId(post.getId());
postUpdate.setTitle("hibernate");
Post updatedPost = postRepository.save(postUpdate); // merge
Assertions.assertThat(entityManager.contains(updatedPost)).isTrue();
Assertions.assertThat(entityManager.contains(postUpdate)).isFalse();
Assertions.assertThat(updatedPost == postUpdate);
List<Post> all = postRepository.findAll();
Assertions.assertThat(all.size()).isEqualTo(1);
}
}
merge 되는 경우에는 파라미터로 넘긴 postUpdate는 영속성 관리에 있지 않으므로 변화 감지를 하지 않는다. 안정하게 하려면 리턴 받은 값을 사용한다. 리턴 받은 값은 perisist던 merge던 영속성 관리를 받는다.