EntityManager 내부의 저장소인 영속성 컨텍스트에 대해 알아보았다. em.persist, em.find 수행시 영속성 컨텍스트의 1차 캐시에 보관되며. INSERT, UPDATE 쿼리는 쓰기 지연 저장소에 보관된다. 그리고 flush 호출시 영속성 컨텍스트의 변경사항을 DB에 반영하며 쓰기 지연 저장소의 모든 쿼리를 날린다.
이번 포스팅에선 객체-테이블, 필드-컬럼, 기본 키 매핑에 대해 알아보자.
@Entity 가 붙은 클래스는 JPA가 관리하며 이를 엔티티라고 한다. 엔티티는 클래스와, 엔티티의 모든 필드는 테이블의 컬럼과 자동으로 매핑된다. 이때 엔티티의 NoArgsContsructor (기본생성자)는 꼭 필수로 만들어두어야 한다.
@Table 은 엔티티와 매핑할 테이블을 지정하는 어노테이션이다.
속성
<property name="hibernate.hbm2ddl.auto" value="update" />
pom.xml 에 위의 설정을 추가하면 @Entity 가 추가된 클래스의 필드를 열로 하는 테이블을 자동으로 생성하거나 수정하는 DDL을 실행한다. value 값을 무엇으로 설정하느냐에 따라 자동 생성 방식이 결정된다.
운영서버에서는 절대 테이블 자동생성 옵션을 사용하면 안된다. create 시 모든 데이터베이스가 초기화되어 DB의 데이터가 날라가며, update 시 컬럼을 추가하면서 테이블에 lock 이 걸려 DB가 마비될 수 있다.
기본키 매핑을 수행한다.
매핑할 컬럼값 관련 속성을 지정할 때 사용한다. 별도 지정 속성이 필요없다면 생략가능하다.
enum 타입을 매핑할 때 사용한다. 기본은 EnumType.ORDINAL 로 되어있어 enum 순서를 컬럼값으로 저장하나, enum 이 추가되면 ORDINAL 은 순서가 꼬여서 문제가 발생한다. enum 매핑 시 꼭 EnumType.String 으로 사용하자.
VARCHAR 이상의 긴 문자열과 매핑할 때 사용한다.
컬럼과 매핑하지 않는다. @Entity 기반 테이블 자동생성 시에도 컬럼이 생성되지 않는다. DB에 저장하지 않고 어플리케이션의 메모리상에서 값을 보관할 때 사용한다.
기본키 매핑에 사용하는 어노테이션이다. 기본 키를 직접 부여할 경우 @Id만 사용하면 된다.
기본키를 자동 생성하여 사용할 때 활용하는 어노테이션이다. DB에 따라 IDENTITY, SEQUENCE 주로 두가지 전략을 사용한다.
IDENTITY 전략
IDENTITY 전략은 기본키 생성을 DB에게 위임하는 전략이며 MySQL 에서 주로 사용한다. 기본키를 Null 로 전달하면 DB 가 자동생성하여 부여한다.
그런데 JPA 는 persist 후 영속성 컨텍스트에 {PK:엔티티} 로 보관하고, INSERT 쿼리는 flush 시점에 호출하는데, IDENTITY 전략은 INSERT 를 수행해야 PK가 생성된다. 따라서 IDENTITY 전략에서는 쓰기 쿼리 지연이 불가능하다. persist 시점에 즉시 INSERT 를 호출하여 PK를 받아와 영속성 컨텍스트에 엔티티를 보관한다.
SEQUENCE 전략
SEQUENCE 전략은 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트인 시퀀스를 활용하는 방식이며 주로 오라클에서 사용한다. 우선 클래스에서 SequenceGenerator 로 시퀀스를 생성한다.
@SequenceGenerator
@GenerateValue 의 generator 속성으로 생성한 시퀀스 생성기 이름을 넣어주면 적용된다. 어플리케이션이 시퀀스를 받아올 때 DB 에게 요청을 해서 하나씩 받아오는 것은 삽입시마다 네트워크 요청이 수행되므로 자원 낭비이다. 그래서 한번에 시퀀스 범위를 받아온 뒤 메모리에서 받아 사용하는데, 이 범위를 정하는 속성이 allcationSize 이다. 이 범위를 너무 크게하면 웹서버를 내릴 때, 받아오고 사용하지 않은 시퀀스는 구멍이 생기기에 최적화가 중요하다.
클래스와 테이블의 매핑은 @Entity 로 한다. @Entity 가 추가된 클래스를 엔티티라고 한다. @Entity 는 기본 생성자가 필수이다. unique 는 @Table에서 지정한다.
JPA 의 테이블 자동생성 DDL 기능을 사용할 수 있다. 단 운영서버는 사용하지 않는 것이 좋다.
엔티티의 필드는 자동으로 테이블의 컬럼과 매핑되는데, 속성을 정할 시 @Column 을 사용하자.
기본키는 @GenerateValue 로 자동생성 지정한다. MySQL은 주로 IDENTITY 전략을, Oracle 은 주로 SEQUENCE 전략을 사용한다.