스프링 데이터 JPA-16.Repository, Repository.save() 메소드
스프링 데이터 JPA: JPA Repository
@EnableJpaRepositories
- 스프링 부트 사용할 때는 사용하지 않아도 자동 설정 됨.
- 스프링 부트 사용하지 않을 때는 @Configuration과 같이 사용.
@Repository 애노테이션을 붙여야 하나 말아야 하나…
- 안붙여도 된다.
- 이미 붙어 있어요. 또 붙인다고 별일이 생기는건 아니지만 중복일 뿐.
스프링 @Repository
- SQLExcpetion 또는 JPA 관련 예외를 스프링의 DataAccessException으로 변환 해준다.
스프링 데이터 JPA: 엔티티 저장하기
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 상태로 변경하고 그 복사본을 반환.
@PersistenceContext
private EntityManager entityManager;
@Test
public void crud(){
Post post = new Post();
post.setTitle("jpa");
Post savedPost = postRepository.save(post); // persist
assertTrue(entityManager.contains(post));
assertTrue(entityManager.contains(savedPost));
assertTrue(post == savedPost);
Post postUpdate = new Post();
postUpdate.setId(post.getId());
postUpdate.setTitle("update post");
Post updatedPost = postRepository.save(postUpdate); // merge
assertTrue(entityManager.contains(updatedPost));
assertFalse(entityManager.contains(postUpdate)); // postUpdate 관리 안한다
assertFalse(updatedPost == postUpdate);
List<Post> all = postRepository.findAll();
assertEquals(all.size(), 1);
}