[JPA] 엔티티 매핑
Updated:
들어가며
해당 글은 자바 ORM 표준 프로그래밍을 정리한 글입니다.
@Entity와 Entity에 적용할 수 있는 어노테이션에 대해 알아 본다. Entity에 대해서 가장 기초적인 어노테이션이며 간단하게 개념 정도와 사용법에 대해서 예제와 함께 알아 보자~
@Entity
- JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다.
@Entity 적용 시 주의사항
- 기본 생성자는 필수다(파라미터가 없는 public 또는 protected 생성자)
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
- 저장할 필드에 final을 사용하면 안 된다.
@Table
- @Table은 엔티티와 매핑할 테이블을 지정할 때 사용
option | description |
---|---|
name | 매핑할 테이블 이름 |
catalog | catalog 기능이 있는 데이터베이스에서 catalog를 매핑한다. |
schema | schema 기능이 있는 데이터베이스에서 schema를 매핑한다. |
uniqueConstraints(DDL) | DDL 생성 시에 유니크 제약조건을 만든다. 참고로 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용된다. |
다양한 매핑 사용
@Enumeated
- Java의 enum을 사용하려면 해당 어노테이션으로 매핑해야 한다.
@Temporal
- Java의 날짜 타입은 해당 어노테이션을 사용해서 매핑한다.
@Lob
- 데이터베이스의 CLOB 타입으로 저쟁하기 위해서는 해당 어노테이션을 사용해서 매핑한다.
데이터베이스 스키마 자동 생성
옵션 설명
option | description |
---|---|
create | 기존 테이블을 삭제하고 새로 생성한다. DROP + CREATE |
create-drop | create 속성에 추가로 애플리케이션을 종료할 때 생성한 DDL을 제거한다. DROP + CREATE + DROP |
update | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정한다. |
validate | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리케이션을 실행하지 않는다. 이 설정은 DDL을 수정하지 않는다. |
none | 자동 생성 기능을 사용하지 않으려면 유효하지 않는 값으로 설정한다. |
기본 키 매핑
직접 할당
- @Id 어노테이션만 사용하는 경우 id를 직접 할당 한다.
- @Id 에 적용가능한 자바 타입
- 자바 기본형
- 자바 래퍼형
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
- em.persist()를 호출하기 전에 애플리케이션에서 직접 식별자 값을 할당
자동 생성
- @GeneratedValue 어노테이션을 이용해 자동 키 생성 전략으로 변경한다.
IDENTITY
- 기본 키 생성을 데이터베이스에 위임한다.
- 데이터베이스에 엔티티를 저장해서 식별자 값을 획득 한 후 영속성 컨텍스트에 저장
- Mysql의 경우 Auto_Increment로 생성되어 insert시에 값이 증가하게 된다.
- 해당 방식은 쓰기 지연 방을 사용할 수 없는데, 식별자 값이 insert 이후에 생성이 되기 때문에 insert 후에 영속성 컨텍스트에 저장을 할 수 있다.
SEQUENCE
- 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
- 데이터베이스 시퀀스에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- em.persist() 호출 전 데이터베이스에서 시퀀스를 사용해 식별자를 식조회 후 식별자를 엔티티에 할당 한 후에 엔티티를 영속성 컨텍스트에 저장 후 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 데이터베이스로 저장
- 데이터베이스 총 2회의 통신이 필요
- 식별자를 구하려고 데이터베이스 시퀀스를 조회한다.
- 조회한 시퀀스를 기본 키 값으로 사용해 데이터베이스에 저장한다.
- @SequenceGenerator : 시퀀스를 생성관련 설정 어노테이션
TABLE
- 키 생성 테이블을 사용한다.
- 데이터베이스 시퀀스에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장
- sequence 방식과 비슷하지만 키 생성 테이블을 하나 만들어서 사용하는 전략
- 모든 데이터베이스에 적용 가능
- sequence를 select하고 해당 값을 insert 후 sequence 값을 update까지 하기 위해 총 3번의 조회가 발생
- @TableGenerator 활용
필드와 컬럼 매핑:레퍼런스
Column
- 속성 기능 기본값
option | description | default |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable | insert할 때 해당 필드 포함 유무, false인 경우 읽기 전용 | true |
updatable | update할 때 해당 필드 포함 유무, false인 경우 읽기 전용 | true |
nullable | 해당 어노테이션을 추가하면 해당 값에 null 값을 허용 | true |
unique | 해당 필드에 유니크 DDL 추가 | false |
length | string에 길이 제한 추가 | 255 |
precision, scale | precision은 소수점을 포함한 전체 자릿수를 scale은 소수의 자릿수다. double, float에는 적용되지 않음 | precision=19, scale=2 |
- @Column 생략하게 되면 자바 기본형의 경우 not null이 추가 된다.
- 기본 타입의 경우 null 값이 되지 않으므로 @Column을 생략하게 되면 NOT NULL로 DDL이 생성 되지만 @Column을 추가하면 NULL로 생성이 된다. nullable의 옵션이 기본값이 true이기 때문이다.
코드
@Entity
public class Member {
...
private int age;
@Column
private int age2;
private Integer age3;
}
결과
create table member (
...
age integer not null,
age2 integer,
age3 integer,
...
)
Enumerated
- 자바 enum 타입을 매핑할 때 사용
- ORDINAL과 STRING 방식으로 사용가능하며 각 사용마다 트레이드 오프가 발생
ORDINAL | STRING | |
---|---|---|
장점 | 데이터베이스에 저장되는 데이터 크기가 작다 | 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전하다 |
단점 | 이미 저장된 enum의 순서를 변경할 수 없다 | 데이터베이스에 저장되는 데이터 크기가 ORDINAL에 비해서 크다 |
코드
@Entity
public class Member {
...
@Enumerated(EnumType.STRING)
private MemberStatus stringStatus;
@Enumerated(EnumType.ORDINAL)
private MemberStatus ordinalStatus;
...
}
결과
create table member (
...
ordinal_status integer,
string_status varchar(255),
...
)
Temporal
- 날짜 타입(Date, Calendar만 사용 가능)을 매핑할 때 사용
Type | description |
---|---|
DATE | 날짜, 데이터베이스 date 타입과 매핑 |
TIME | 시간, 데이터베이스 time 타입과 매핑 |
TIMESTAMP | 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 |
Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑
- 매핑하는 필드 타입이 문자면 CLOB으로 매핑하고 나머지는 BLOG에 매핑한다.
- BLOG: byte[]
- CLOB: String, char[]
코드
@Entity
public class Member {
...
@Lob
private String text;
@Lob
private char[] chars;
@Lob
private byte[] bytes;
...
}
결과
create table member (
...
text clob,
bytes blob,
chars clob,
...
)
Transient
- 필드에 매핑하지 않게 해주며, 데이터베이스에 저장 및 조회가 되지 않는다.
- 어노테이션을 이용하거나 transient를 사용해서 데이터베이스 필드에서 제외시킨다.
// 방법 1
@Transient
private Long empty;
// 방법 2
private transient Long empty;
Access
- 엔티티 데이터에 접근하는 방식을 지정
- 필드 접근 : 필드에 직접 접근
- 프로퍼티 접근 : 접근자 (Getter)를 사용한다.
마치며
@Entity와 Entity에 적용할 수 있는 어노테이션에 대해서 알아보았다. 기본 키 매핑에 대해서 정확하게 알고 있지 않아서 질문이 들어왔을 때 설명을 못 했었는데 이번에 정리하면서 좀 더 자세하게 알아본 것 같다.👍
JPA를 사용하는데 있어서 기초가 되는 부분이라 한번은 자세히 읽어보고 넘어가는걸 추천한다!😊
- JPA 리뷰 글 보러가기
Leave a comment