[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회의 통신이 필요
    1. 식별자를 구하려고 데이터베이스 시퀀스를 조회한다.
    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를 사용하는데 있어서 기초가 되는 부분이라 한번은 자세히 읽어보고 넘어가는걸 추천한다!😊



Leave a comment