EntityManager.persist(entity);
persist() 메서드는 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장한다.
영속성 컨텍스트에 저장된 엔티티는 엔티티 매니저를 사용해서 접근할 수 있고 관리할 수 있다.
엔티티의 생명주기
//객체를 생성한 상태(비영속)
Cafe cafe = new Cafe();
cafe.setId(1);
cafe.setMenu(“아메리카노”);
cafe.setPrice(5000);
위 코드는 순수한 객체 상태이며 아직 엔티티 매니저를 통해 영속성 컨텍스트에 저장되지 않았다.
이러한 상태를 비영속 상태라 한다.
em.persist(cafe); //객체를 영속성 컨텍스트에 저장한다
위의 비영속상태의 객체를 엔티티 매니저의 persist() 메서드를 통해 영속성 컨텍스트에 저장해주었다.
이렇게 되면 cafe라는 엔티티가 영속 상태가 되는 것이다. 영속 상태가 된다는 것은 영속성 컨텍스트에 의해 관리된다는 뜻이다.
영속성 컨텍스트의 특징
//객체를 생성한 상태(비영속)
Cafe cafe = new Cafe();
cafe.setId(1); //@Id를 통해 식별자 값으로 설정 -> @Id private Long id;
cafe.setMenu(“아메리카노”);
cafe.setPrice(5000);
em.persist(cafe); //객체를 영속성 컨텍스트에 저장한다
이 코드를 실행 하면 1차 캐시에 cafe 엔티티를 저장한다. 하지만 flush 또는 트랜잭션 커밋을 해주지 않았기에 데이터베이스에는 저장되지 않았다.
1차 캐시에 저장된 값을 조회하기 위해서는 엔티티에 @Id값을 통해 설정된 식별자 값이 필요하다.
엔티티를 조회하는 방법은 다음과 같다.
Cafe cafe = em.find(Cafe.class, 1L);
엔티티 매니저의 find() 메서드의 첫 번째 파라미터는 엔티티 클래스의 타입이고, 두 번째는 조회할 엔티티의 식별자 값이다.
em.find()는 우선 영속성 컨텍스트에 저장되어있는 1차캐시에서 엔티티를 찾는다.
만약 찾는 엔티티가 없다면 데이터베이스에서 조회하고 조회한 엔티티를 1차 캐시에 저장한 후 영속상태의 엔티티를 반환한다.
쓰기지연
엔티티 매니저는 트랜잭션 커밋 또는 flush() 하기 전까지 데이터 베이스에 엔티티를 저장하지 않고 쓰기 지연 SQL저장소에 INSERT SQL을 차곡차곡 모아둔다. 그리고 트랜잭션을 커밋 할 때 모아둔 쿼리를 데이터베이스에 보내는데
이것을 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)이라 한다.
-> 이 기능을 잘 활용하면 성능 최적화를 할 수 있다.
JPA로 엔티티를 수정할 때는 단순히 엔티티를 조회해서 데이터만 변경하면된다!
//영속 엔티티 조회
Cafe cafe = em.find(Cafe.class, 1L);
//영속 엔티티 수정
cafe.setMenu(“카페라떼”);
이렇게만 하면 수정한 내용이 데이터베이스에 반영된다.
엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능을 변경 감지(dirty checking)이라 한다.
JPA는 엔티티를 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해두는데 이것을 스냅샷 이라 한다.
그리고 플러시(flush)시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 보낸다고 데이터 베이스 트랜잭션을 커밋한다.
변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용된다.
엔티티를 삭제하려면 삭제 대상 엔티티를 조회한 다음에 em.remove(엔티티)를 사용하여 삭제해주면된다.
Cafe cafe = em.find(Cafe.class, 1L);
em.remove(cafe)
당연히 엔티티가 즉시 삭제되는 것이 아니라 트랜잭션을 커밋해서 플러시를 호출하면 실제 데이터 베이스에 삭제 쿼리를 전달한다.
em.detach(엔티티) 메서드를 통해 특정 엔티티를 준영속 상태로 만든다.
//카페 엔티티 생성, 비영속 상태
Cafe cafe = new Cafe();
cafe.setId(1L);
cafe.setMenu(“아메리카노”);
cafe.setPrice(5000);
//카페 엔티티 영속상태
em.persist(cafe);
//카페 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(cafe);
tx.commit();//트랜잭션 커밋
em.detach(엔티티) 메서드를 호출 하는 순간 1차 캐시부터 쓰기 지연 SQL 저장소까지 해당 엔티티를 관리하는 모든 정보가 제거된다.
영속 상태였다가 더는 영속성 컨텍스트가 관리하지 않는 상태를 준영속 상태라 한다.
em.clear() 메서드를 통해 영속성 컨텍스트에 저장된 모든 정보를 초기화 시킨다.
//엔티티 조회, 영속상태
Cafe cafe = em.find(Cafe.class, 1L);
em.clear();//영속성 컨텍스트 초기화
//준영속 상태
cafe.setMenu(“카페라떼”);
tx.commit();//트랜잭션 커밋
em.close() 메서드를 사용하여 영속성 컨텍스트를 종료시킨다.
영속성 컨텍스트를 종료하면 해당 영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 모두 준영속 상태가 된다.
자바 ORM 표준 JPA 프로그래밍 - 저자 김영한