설정파일로 EntityMangerFactory 를 생성하고, 거기서 EntiyManager 를 생성하여 멤버 메서드로 JPA의 DB 접근을 수행한다. em.persist, em.find, em.remove 등을 통해 CRUD 가 이루어지며, 수정은 객체를 변경하면 자동 반영된다.
JPA 의 수정 자동반영은 영속성 컨텍스트의 존재로 이루어진다. 영속성 컨텍스트에 대해 알아보자
엔티티란 DB 의 테이블과 1:1 매핑되는 하나의 클래스라고 생각하면 된다. JPA 에서 Entity 는 @Entity 어노테이션을 붙여 JPA가 관리하는 클래스를 의미한다.
엔티티는 위와 같은 생명주기를 갖는다. 각 상태는 @Entity 의 객체, 즉 엔티티가 영속성 컨텍스트의 관리를 받는지 여부에 따라 결정된다.
Member memberA = new Member();
memeber.setId(1);
member.setName("kim");
비영속상태는 엔티티가 새로 생성된 상태이며, 아직 영속성 컨텍스트에 들어가지 못한 상태를 의미한다.
em.persist(memberA);
영속상태는 엔티티가 persist 나 find 등에 의해 영속성 컨텍스트에게 관리를 받게 된 상태를 의미한다.
em.detach(memberA);
em.clear();
em.close();
준영속이란 영속성 컨텍스트에서 해당 엔티티를 분리시킨 것을 말한다. 분리되는 순간 엔티티는 영속성 컨텍스트의 관리를 받지 못하게된다. 영속성 컨텍스트를 clear 로 초기화 시키면 모든 엔티티가 준영속화 된다.
em.remove(memberA);
DB 에 쿼리를 날려 삭제를 요청한다. 영속성 컨텍스트에서 분리되는 것은 물론 DB 에서도 제거된다.
영속성 컨텍스트란 Entity Manager 내부에 존재하는 저장소이다. PK와 엔티티로 1차 캐시를 저장하는 한편, pesist 등의 쿼리를 저장해 쓰기 지연을 담당하기도 한다. em.persist 나 em.find 를 수행하게 되면 엔티티가 영속성 컨텍스트에 저장되며 관리를 받는다.
em.persist 를 통해 영속화를 수행하거나, em.find 로 조회를 수행하면 영속성 컨텍스트의 1차 캐시에 엔티티가 등록되어 관리된다. 이 때 동일한 엔티티를 조회하게 되면 DB에 쿼리문을 날리지 않고 영속성 컨텍스트의 엔티티를 반환한다.
em.persist 로 영속화를 수행하면 영속성 컨텍스트에 엔티티가 저장되고, 쓰기 지연 SQL 저장소에 INSERT 쿼리문이 저장된다. 쓰기 지연의 INSERT 문은 Flush가 되는 순간 DB에 요청된다.
영속성 컨텍스트는 엔티티가 1차 캐시에 저장되는 순간의 스냅샷을 함께 저장한다. 그리고 flush 가 호출되면 들어오면 스냅샷과 현재 엔티티를 비교해, 변경이 존재한다면 지연 SQL 저장소에 Update 쿼리를 추가한다. flush 는 또한 쓰기 지연 SQL 저장소의 모든 쿼리들을 요청한다.
플러시란 영속성 컨텍스트와 DB를 일치시키도록 반영하는 것이다. 영속성 컨텍스트 엔티티의 변경사항이 존재하면 쓰기지연 SQL 저장소에 Update 쿼리를 추가한다. 그 후 쓰기 지연 SQL 저장소의 모든 쿼리들이 DB로 요청된다. 이 때 영속성 컨텍스트를 비우는게 아님에 유의한다.
em.persist(memberA);
em.persist(memberB);
query = em.creataeQuery("select m from Member m", Member.class); //아직 위의 결과가 반영 안됨.
List<Member> members = query.getResutlList();
JPQL 쿼리 실행시 DB에 직접 요청을 수행하는데, 이전의 쓰기 지연이 존재한다면 다른 결과를 얻는 문제가 생길 것이다. 그래서 JPQL 쿼리 실행시 flush 를 통해 모든 쓰기 지연 저장소의 쿼리를 실행한다.
em.persist 나 em.find 를 수행하면 영속성 컨텍스트의 1차캐시에 보관된다.
INSERT, UPDATE 같은 쿼리는 쓰기 지연 SQL 저장소에 저장되며 flush 시에 한번에 수행된다.
flush 는 commit 과 JPQL 호출시 수행된다. 이 때 더티체킹으로 영속성 컨텍스트의 변경사항을 UPDATE 쿼리문으로 반영하며, 쓰기 지연 SQL 저장소의 쿼리문들을 한번에 DB에 요청한다.