Open dbwp031 opened 1 year ago
영속성 컨텍스트
가상의 DB
영속성 컨텍스트 특징
엔티티 매니저
비영속 (new/transient)
영속성 컨텍스트와 전혀 관계가 없는 상태. 엔티티 객체를 생성했지만 아직 영속성 컨텍스트에 저장하지 않은 상태
Member member = new Member();
영속(managed)
영속성 컨텍스트에 저장된 상태, 영속성 컨텍스트에 의해 관리된다는 뜻
em.persist(member);
준영속(detached) 영속성 컨텍스트에 저장되었다가 분리된 상태. 관리하던 영속 상태의 엔티티를 더 이상 관리하지 않는 상태. 약간 휴지통 안에 들어있는 파일 느낌.
// 엔티티를 영속성 컨텍스트에서 분리해 준영속 상태로 만든다.
em.detach(member);
// 영속성 컨텍스트를 비워도 관리되던 엔티티는 준영속 상태가 된다.
em.clear();
// 영속성 컨텍스트를 종료해도 관리되던 엔티티는 준영속 상태가 된다.
em.close();
엔티티
식별자 값 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다. 영속 상태는 식별자 값이 있어야 한다. 식별자는 기본 키이다.
1차 캐시
em.persist()
를 사용하면, DB에 저장되는 것이 아니라 1차 캐시에만 저장된다. 그렇게 하면, 이후 select
구문이 일어났을 때, db에 접근하지 않고 1차 캐시에서 가져올 수 있으므로 cost가 준다. 트랜잭션 커밋시 쌓아둔 쿼리문을 실행시켜 반영해준다. 따라서 생명주기가 하나의 트랜잭션과 같다.
디비 저장, flush
JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 db에 반영하는데 이를 flush
라 한다.
동일성 보장
영속성 컨텍스트는 엔티티 동일성
을 보장한다.
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.print(a==b) // true
트랜잭션을 지원하는 쓰기 지연
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 INSERT SQL
을 모아둔다. 그리고 트랜잭션을 커밋할 때 쿼리를 DB로 보낸다.
변경 감지
flush()
가 실행될 때, 엔티티와 snapshot을 비교하여, 변경이 감지되면 update 쿼리를 날린다.
지연 로딩 객체 초기화를 지연하여 실제로 사용할 때 사용할 수 있도록 한다.
OneToMany, ManyToOne
과 같이 양방향 관계를 맺는 엔티티의 상태 변화를 전이시킬 때 사용한다.
종류
CascadeType.ALL
: 모든 Cascade 적용CascadeType.PERSIST
: 엔티티를 영속화할 때, 연관된 엔티티도 함께 영속화CascadeType.MERGE
: 엔티티 상태를 병합할 때, 연관된 엔티티도 모두 병합CascadeType.REMOVE
: 엔티티 제거할 때, 연관된 엔티티도 모두 제거CascadeType.DETACH
: 부모 엔티티를 detach()하면, 연관된 애도 detach()하여 변경 사항을 반영하지 않는다.CascadeType.REFRESH
: 상위 엔티티 새로고침할 때, 연관된 엔티티도 모두 새로고침.사용 위치
웬만하면 @OneToMany
일 듯. 보드(OneToMany) - 댓글(ManyToOne
에서 댓글에 케스케이드를 걸어주면, 댓글을 삭제하면 보드도 삭제될 수가 있다.
보수적으로 cascade 룰을 막아두고, 이후 편리하게 쓸 수 있는 usecase가 있다면 그때 열어준다.
데이터로 댓글과 대댓글에 대한 계층적인 구조가 반영되어 있지 않다.
대댓글 기능과 관련된 내용을 정리한다.