[개요]
User 엔티티의 테스트를 진행 하던 중 다음 코드에서 의문이 생겼다.
id를 넣어주지 않았는데 어떻게 getId()가 동작하지 !? 이를 위해 먼저 영속화에 대한 개념을 알아보자.
영속성 컨텍스트
영속성 컨텍스트는 엔티티를 보관하는 저장소라고 할 수 있다. JPA에서는 엔티티를 영속성 컨텍스트에 넣어서 관리하기 때문에 매우 중요하다. 영속성 컨텍스트는 쓰기 지연 저장소와, 1차 캐시로구성되어 있다.
memberA를 영속화 (persist())했을 때 일어나는 과정을 위의 그림을 통해 살펴보자.
- persist(memberA)를 호출한다.
- 1차 캐시에 memberA를 저장한다. 동시에 SQL문을 생성하여 쓰기 지연 SQL 저장소에 저장한다.
- Transaction이 끝나는 시점에 쓰기 지연 저장소에 있던 SQL이 실행되고 DB에 데이터가 들어간다.
영속성 컨텍스트는 엔티티를 식별자 값 (@Id)으로 관리한다. 따라서 영속 상태는 식별자 값이 반드시 있어야 하는데 다음과 같이 AUTO_INCREMENT로 선언되어 있는 경우에는 어떻게 동작할까?
GeneratedValue 전략
generatedValue에서는 기본키를 자동으로 생성하는 방법을 지정할 수 있다.
IDENTITY 전략
기본키의 생성을 데이터베이스에게 위임하는 방식으로 데이터베이스가 자동으로 AUTO_INCREMENT를 하여 기본키를 생성하는 전략.
이 전략은 PK의 값을 데이터베이스에 INSERT한 이후에 알 수 있기 때문에 persist()하는 시점에 쿼리문이 나간다. 즉, 쓰기 지연 저장소를 사용하지 않는다.
- [추가 학습] 쓰기 지연 저장소
- 영속성 컨텍스트는 보통 트랜잭션이 끝나는 시점에 쓰기 지연 저장소에 있는 쿼리문을 실행하여 데이터베이스에 데이터를 입력하는데, 이 쓰기 지연 저장소라는 것은 INSERT문을 모아서 데이터베이스에 반영하기 때문에 성능 최적화의 이점이 있으며, 영속성 안의 엔티티의 컬럼 값이 바뀌면 이에 DB에 자동으로 업데이트 해주는 이점이 있다.
SEQUENCE
데이터베이스의 Sequence만 먼저 조회하여 Sequence와 엔티티를 함께 1차에 저장하고, 커밋이 일어나는 시점에 Entity를 저장하는 전략.
TABLE
@TableGenerator 어노테이션을 이용하여 키 관리 테이블을 따로 사용하는 방법으로 모든 데이터베이스에 사용할 수 있다.
AUTO
JPA Generated 디폴트 값으로 각 데이터베이스에 맞춰 기본키를 자동으로 생성한다.