2023-05-23 EFUB 백엔드 세션을 듣고 정리한 내용입니다.
비영속 (new/transient)
: 영속성 컨텍스트와 무관한 상태. 엔티티를 생성하고 아직 저장하지 않았을 경우 비영속에 해당됨.
영속(managed)
: 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태.
영속성 컨텍스트에 의해 관리되는 상태.
준영속(detached)
: 영속성 컨텍스트에 의해 관리되다가 영속성 컨텍스트에서 분리되어 ,더 이상 영속성 컨텍스트에 의해 관리되지 않는 상태
삭제(removed)
: 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한 상태
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
em.persist(fubyA); // 영속성 컨텍스트 내부 1차 캐시에 저장 (영속화)
transaction.commit(); // 트랜잭션 커밋.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보냄.
1) persist()로 엔티티를 영속화
2) 엔티티는 영속성 컨텍스트 1차 캐시에 저장 && JPA가 엔티티를 분석해 INSERT 쿼리를 생성하여 쓰기 지연 SQL 저장소에 쌓아둠
3) 트랜잭션을 커밋하면 쓰기 지연 SQL 저장소에 있
는 쿼리들이 flush 되면서 DB에 날아간다.
4) DB 트랜잭션 커밋.
1) 트랜잭션을 커밋
2) 영속성 컨텍스트 내부에서 flush 호출
3) 엔티티랑 스냅샷을 비교하여 변경된 엔티티 찾음
* 스냅샷 : 1차 캐시 안에 들어오는 최초의 상태를 본떠둔 것
4) 변경된 것은 UPDATE 쿼리를 생성하여 쓰기 지연 SQL 저장소에 보냄
5) 쓰기 지연 저장소의 SQL을 DB에 보냄
6) DB 트랜잭션 커밋.
1) em.remove(memberA)로 삭제할 엔티티를 넘겨주면 DELETE 쿼리를 쓰기 지연 SQL 저장소에 등록
이때 memberA 엔티티는 영속성 컨텍스트에서 제거됨
2) 트랜잭션을 커밋하면 flush
호출하여 DB에 DELETE 쿼리 전달
즉시 로딩
지연 로딩
연관된 엔티티까지 함께 조회할 필요는 없을 때 사용
@ManyToOne(fetch = FetchType .LAZY)로 설정한다.
@ManyToOne, @OneToOne과 같이 @XXXToOne 어노테이션들은 기본이 즉시 로딩(EAGER) 이다.
실무에서는 즉시 로딩을 지양하도록 한다.
대부분의 JPA 구현체는 즉시로딩을 최적화하기 위해 가능하면 조인 쿼리를 사용하는데 이때 조인이 중첩되면 오히려 쿼리의 성능을 저하시킬 수 있다.
즉시로딩은 JPQL에서 N+1 문제를 일으킨다.
➕ N+1 문제
: 객체를 데이터베이스에서 불러올 때 연관관계 객체를 불러오기 위한 1개의 쿼리가 아닌, N개의 쿼리가 생성되는 문제이다.
: 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때 사용, 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공하는 기능일 뿐 연관관계 매핑과 관련이 없음
(ex) 부모 엔티티를 영속 컨텍스트에 저장할 때 자식 엔티티도 함께 영속 컨텍스트에 저장하고 싶을 때
All
: 생명주기를 다 맞추려 할 때
PERSIST
: 저장할 때만 영속성 전이를 이용할 때
REMOVE
: 삭제
MERGE
: 병합
REFRESH
: refresh
DETACH
: detach
[1:N] 연관관계인 엔티티에 항상 사용하는 것은 아님
특정 엔티티를 관리하는 엔티티가 하나일 때
영향을 주는 부모 엔티티가 여럿이면 영속성 전이를 사용할 이유가 없음
자식의 소유자가 부모 하나일 때, 단일 엔티티에 종속적일 때만 영속성 전이 사용의 의미가 있음
생명주기가 동일할 때 사용
부모 엔티티와 연관관계가 끊어진 자식 엔티티, 참조가 제거된 엔티티
orphanRemoval = true로 설정
@Entity
public class Parent { …
@OneToMany(mappedBy=“parent”, orphanRemoval = true)
private List<Child> childList = new ArrayList();
}
em.remove(parent); 실행하면 child 객체들도 삭제됨
CascadeType.ALL + orphanRemoval=true
부모 엔티티를 통해서 자식의 생명주기를 관리
Validation 라이브러리에서 제공하는 annotation을 이용
Validator 인터페이스를 구현하는 클래스를 생성하고 그 클래스를 스프링 빈으로 등록해서 사용
제약 조건 Annotation
@NotNull
: null을 허용하지 않음
@NotEmpty
: null과 “”를 허용하지 않음
@NotBlank
: null과 “”과 “ “을 허용하지 않음
@AssertTrue
: 값이 참이어야 함, null도 허용함
@Pattern
: 특정 정규표현식을 만족해야 함
@Size
: 지정된 경계(포함) 사이의 값을 가져야 함
@Min
: 지정된 최솟값보다 크거나 같은 값을 가져야 함
@Max
: 지정된 최댓값보다 작거나 같은 값을 가져야 함