•
JPA를 사용함에 있어서 가장 중요한 일은 엔티티와 테이블을 정확히 매핑하는 것이다. 따라서 매핑 어노테이션을 숙지하고 사용해야 한다.
•
JPA는 다양한 매핑 어노테이션을 지원하며 크게 4가지로 분류할 수 있다.
◦
객체와 테이블 매핑: @Entity, @Table
◦
PK 매핑: @Id
◦
필드와 컬럼 매핑: @Column
◦
연관관계 매핑: @ManyToOne, @JoinColumn
1. @Entity
•
@Entity가 붙은 클래스는 JPA가 관리하는 것으로 엔티티라 부른다.
•
속성은 다음과 같다.
◦
name: JPA에서 사용할 엔티티 이름을 지정한다. 기본값은 클래스 명이다.
•
@Entity 적용 시 주의사항은 다음과 같다.
◦
기본 생성자는 필수다.(매개변수가 없는 public 또는 protected 생성자)
◦
final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
◦
저장할 필드에 final을 사용하면 안 된다.
•
JPA가 엔티티 객체를 생성할 때, 기본 생성자를 사용하므로 이 생성자는 바드시 있어야 한다.
◦
생성자가 없는 경우, 기본 생성자를 만드나 생성자가 하나라도 없는 경우, 기본 생성자를 만들어주어야 한다.
2. @Table
•
@Table은 엔티티와 매핑할 테이블을 지정한다. 생략하면 매핑한 엔티티 이름을 기본값으로 사용한다.
•
속성은 다음과 같다.
◦
name: 매핑할 테이블 명으로, 기본값은 테이블명이다.
◦
catalog: catalog 기능이 있는 데이터베이스에서 catalog를 매핑한다.
◦
schema: schema 기능이 있는 데이터베이스에서 schema를 매핑한다.
◦
uniqueConstraints: DDL 생성 시, 유니크 제약조건을 만든다. 2개 이상의 복합 유니크 제약조건도 만들 수 있다.
▪
단, 자동 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용된다.
3. 다양한 매핑 사용
4. 데이터베이스 스키마 자동 생성
•
JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.
•
JPA는 클래스의 매핑 정보와 데이터베이스 방언을 사용해서 데이터베이스 스키마를 생성한다.
•
hibernate.hdm2ddl.auto의 값을 create로 바꾸면 어플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성한다.
◦
create: 기존 테이블을 삭제하고 새로 생성한다.
◦
create-drop: create 속성에 추가로 어플리케이션을 종료할 때 생성한 DDL을 제거한다.
◦
update: 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정한다.
◦
validate: 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 어플리케이션을 실행하지 않는다.
•
운영서버에서 DDL을 수정하는 옵션은 절대 사용해선 안 된다. 개발 서버나 개발 단계에서만 사용해야 한다.
◦
개발 초기 단계는 create, update
◦
초기화 상태로 자동화된 테스트를 진행하는 개발자 환경과 CI 서버는 create, 또는 create-drop
◦
테스트 서버는 update 또는 validate
◦
스테이징과 운영 서버는 validate
5. DDL 생성 기능
•
스키마 자동 생성 기능을 통해 만들어지는 DDL에 어노테이션들을 활용해 제약조건을 추가할 수 있다.
•
@Column, @Table의 속성을 적절히 사용하면 된다.
6. 기본 키 매핑
•
기존에는 @Id 어노테이션만 사용해서 회원의 기본 키를 어플리케이션에서 직접 할당했다.
•
기본 키를 어플리케이션에서 직접 할당하는 대신, 데이터베이스가 생성해주는 값을 사용하려면 어떻게 매핑해야할까?
◦
오라클의 시퀀스 오브젝트, MySQL의 AUTO_INCREMENT같은 기능을 사용해 생성된 값을 기본 키로 사용하는 것 말이다.
•
이처럼 데이터베이스마다 기본 키를 생성하는 방식이 다르므로 이 문제를 JPA는 어떻게 해결할까?
•
JPA가 제공하는 데이터베이스 키 생성 전략은 다음과 같다.
◦
직접 할당: 기본 키를 어플리케이션에서 직접 할당한다.
◦
자동 생성: 대리키 사용 방식
▪
IDENTITY: 기본 키 생성을 데이터베이스에 위임한다.
▪
SEQUENCE: 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
▪
TABLE: 키 생성 테이블을 사용한다.
•
기본 키를 직접 할당하려면 @Id를 사용하면 되고 자동 생성 전략을 사용하려면 @GeneratedValue 속성을 이용해 원하는 키 생성 전략을 선택하면 된다.
1. 기본 키 직접 할당 전략
•
기본 키를 직접 할당하려면 속성을 @Id로 매핑하면 된다. 적용 가능한 자바 타입은 다음과 같다.
◦
자바 기본형, 자바 래퍼형, String, java.util.Date, java.sql.Date, java.math.BigDecimal, java.math.BigInteger
•
기본 키 직접 할당 전략은 em.persist()로 엔티티를 저장하기 전에 어플리케이션에서 기본 키를 직접 할당하는 방법이다.
2. IDENTITY 전략
•
기본 키 생성 전략을 데이터베이스에 위임하는 전략으로 데이터베이스에 영속성 객체를 저장할 때, 기본 키 속성을 비워두면 데이터베이스가 값을 채워준다.
•
@GenerateValue 어노테이션을 사용하고 식별자 생성 전략을 GenerationType.Type을 IDENTITY로 지정하면 된다.
3. SEQUENCE 전략
•
데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트로 SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성한다.
◦
이 전략은 시퀀스를 지원하는 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용할 수 있다.
4. TABLE 전략
•
TABLE 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략이다.
◦
이 전략은 테이블을 사용하므로 모든 데이터베이스에 적용할 수 있다.
•
TABLE 전략을 사용하려면 먼저 키 생성 용도로 사용할 테이블을 만들어야 한다.
5. AUTO 전략
•
AUTO는 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다.
•
데이터베이스를 변경해도 코드를 수정할 필요가 없으므로 특히 키 생성 전략이 아직 확정되지 않은개발 초기 단계나 프로토타입 개발 시 편리하게 사용할 수 있다.
6. 기본 키 매핑 정리
•
영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 엔티티를 영속 상태로 만들려면 식별자 값이 반드시 있어야 한다.
•
em.persist()를 호출한 직후 발생하는 일을 식별자 할당 전략별로 정리하면 다음과 같다.
◦
직접 할당: em.persist()를 호출하기 전, 어플리케이션에서 직접 식별자 값을 할당해야 한다.
◦
SEQUENCE: 데이터베이스 시퀀스에서 식별자 값을 획득한 후, 영속성 컨텍스트에 저장한다.
◦
TABLE: 데이터베이스 시퀀스 생성용 테이블에서 식별자 값을 획득한 후, 영속성 컨텍스트에 저장한다.
◦
IDENTITY: 데이터베이스에 엔티티를 저장해서 식별자 값을 획득한 후, 영속성 컨텍스트에 저장한다.
7. 필드와 컬럼 매핑: 레퍼런스
1. @Column
•
객체의 속성을 테이블 컬럼에 매핑하는 어노테이션으로 가장 많이 사용되며 기능도 많다.
•
속성은 다음과 같다.
◦
name: 필드와 매핑할 테이블의 컬럼 명을 작성한다.
◦
insertable: 엔티티 저장 시 이 필드도 같이 저장한다. false로 설정하면 이 필드는 데이터베이스에 저장하지 않는다. 읽기 전용일 때 사용한다.
◦
updatable: 엔티티 수정 시, 이 필드도 같이 수정한다. false로 설정하면 데이터베이스에 수정하지 않는다.
◦
table: 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용한다.
◦
nullable(DDL): null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시 not null 제약조건이 추가된다.
◦
unique(DDL): @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다. 만약 두 컬럼 이상인 경우, uniqueContsraints를 사용해야 한다.
◦
columnDefinition(DDL): 데이터베이스 컬럼 정보를 제공할 수 있다.
◦
length(DDL): 문자 길이 제약조건, String 타입에만 사용한다.
◦
precision, scale(DDL): BigDecimal 타입에서 사용한다. precision은 소수점을 포함한 전체 자릿수를 scale은 소수의 자릿수다. 아주 큰 숫자나 정밀한 소수를 다루어야할 때 사용한다.
2. @Enumerated
•
자바의 enum 타입을 매핑할 때 사용한다.
•
속성은 다음과 같다.
◦
value
▪
EnumType.ORDINAL(기본값): enum 순서를 데이터베이스에 저장한다.
▪
EnumType.STRING: enum 이름을 데이터베이스에 저장한다.
3. @Temporal
•
날짜 타입(java.util.Date, java.util.Calender)를 매핑할 때 사용한다.
•
속성은 다음과 같다.
◦
value(필수)
▪
TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑한다.
▪
TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑한다.
▪
TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑한다.
4. @Lob
•
데이터베이스 BLOB, CLOB 타입과 매핑한다.
•
매핑하는 필드의 타입이 문자면 CLOB로 매핑하고 나머지는 BLOB로 매핑한다. 지정할 수 있는 속성은 없다.
5. @Transient
•
매핑하지 않을 때 적용한다. 데이터베이스에 저장하지 않고 조회하지도 않는다. 객체에 임시로 어떤 값을 보관할 때 사용한다.
6. @Access
•
JPA가 엔티티 데이터에 접근하는 방식을 지정한다.
◦
필드 접근: AccessType.FIELD로 지정한다. 필드에 직접 접근한다.
◦
프로퍼티 접근: AccessType.PROPERTY로 지정한다. 접근자를 사용한다.
•
설정하지 않으면 @Id의 위치를 기준으로 접근 방식을 설정한다.
◦
@id가 필드에 있으면 AccessType.FIELD로 설정한 것과 같다.
◦
@id가 속성에 있으면 AccessType.PROPERTY로 설정한 것과 같다.