본문 바로가기
강의 정리/자바 ORM 표준 JPA

3. 엔티티 매핑

by 이석준석이 2020. 12. 27.

1. 객체와 테이블 매핑

 

@Entity

  • JPA 가 관리하는 객체이며, 데이터베이스 테이블과 매핑해서 사용한다.
  • 기본 생성자 필수 (public / protected)
  • final 클래스, enum, interface, inner 클래스 사용은 안된다.
  • 저장할 필드에 final 사용은 안된다.

 

  • 속성
    • name
      • JPA에서 사용할 엔티티 이름
      • default 는 객체 명

@Table

  • 속성
    • name
      • 데이터베이스 테이블에 대한 이름을 지정한다.
    • uniqueConstraints
      • 유니크 제약조건을 부여한다.

2. 데이터베이스 스키마 자동 생성

 

옵션

  • hibernate.hbm2ddl.auto
    • create : 시작 시점에 drop
    • create-drop : 종료 시점에 drop
    • update : 변경 부분만 반영 (컬럼을 추가하는 것만 가능하다.)
    • validate : 엔터티와 테이블이 정상적으로 매핑되었는지 확인 시켜준다.
  • 운영 장비에는 절대로 create / create-drop / update 를 사용하면 안된다.

3. 필드와 컬럼 매핑

 

매핑 어노테이션 정리

어노테이션 설명
@Column 컬럼 매핑
@Temporal 날짜 타입 매핑
@Enumerated enum 타입 매핑
@Lob CLOB, BLOB 매핑
@Transient 특정 컬럼은 매핑하고 싶지 않다. (메모리에서만 사용할 것이다.)

 

 

@Column

속성 설명 기본값
name 필드와 매핑할 테이블에서의 컬럼명 객체의 필드이름과 동일하다.
insertable
updatable
컬럼을 수정했을 때, 데이터베이스에 변경 사항을 반항 할 것인가 TRUE
nullable(DDL) null 값의 허용 여부를 설정한다.

false 로 설정하면 not null 제약조건이 붙는다.
 
unique(DDL) 잘 쓰지 않는다. (유니크 제약 조건의 이름이 랜덤값으로 들어가기 때문이다.)

@Table(uniqueConstraints = ...) 으로 이름을 줘서 사용하는 방법을 더 많이 사용한다.
 
columnDefinition 데이터베이스 컬럼 정보를 직접 줄 수 있다.

ex) columnDefinition = "char(1)"
 
length 문자 길이의 제약조건을 줄 수 있다.

오직 String 타입에서만 사용한다.
 
precision,
scale(DDL)
BigDecimal 타입에서 사용한다. (BigInteger도 가능)

precision : 소수점을 포함한 전체 자리수
scale : 소수의 자리수
precision=19,
scale=2

 

@Enumerated

속성 설명 기본값
value EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
EnumType.STRING : enum 이름을 데이터베이스에 저장
EnumType.ORDINAL

 

@Temporal

  • hibernate 최신에서는 LocalDate / LocalDateTime 을 사용하고, @Temporal을 사용할 필요가 없다.
속성 설명 기본값
value - TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑
ex) [2020-01-01]

- TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑
ex) [12:12:12]

- TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑
ex) [2020-01-01 12:12:12]
 

 

@Lob

  • 옵션은 없다.
  • String 이면 CLOB
  • 나머지는 BLOB 으로 매핑된다.

 

@Transient

  • 매핑을 하기 싫은 프로퍼티에 사용한다.

4. 기본키 매핑

 

기본키 직접 할당 : @Id 만 사용

자동 기본키 할당 : @Id + @GeneratedValue

 

@GeneratedValue 옵션 (strategy)

옵션 설명
AUTO Dialect 에 따라서 아래의 옵션 중 알맞은 것을 자동으로 설정해준다.
IDENTITY 기본 키 생성을 데이터베이스에 위임한다.

- MySQL : auto_increment
SEQUENCE 데이터베이스 시퀀스 오브젝트를 통해서 id 값을 세팅해준다.

Hibernate: 
    call next value for hibernate_sequence (기본 시퀀스)

@SequenceGenerator을 통해서 시퀀스를 생성할 수 있다.
TABLE 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.

장점
- 모든 데이터베이스에서 사용 가능하다.

단점
- 성능

 


권장하는 식별자 전략

  • 기본 키 제약 조건
    • null 이면 안된다.
    • 유일해야 한다.
    • 변하면 안된다.
  • 미래를 예측할 수 없으므로
    • Long형 + 대체키 [비즈니스와 전혀 상관없는 키 ex) auto_increment, sequence, uuid] + 키 생성전략

IDENTITY 전략

  • @Id 에 값을 넣으면 안된다.
  • 데이터베이스에 쿼리를 날리면, Null 로 들어가게 되며, 그때 돼서야 db에서 값을 설정한다.

반드시 알아야 할 유의점!!

  • 아직 데이터베이스에 넣기 전에, 1차 캐시의 PK 값이 없으므로 1차 캐시를 세팅할 방법이 없다.
  • 따라서, IDENTITY 전략은 em.persist를 하면, 그 순간 insert query를 날리게 된다.
    • (예전에 봤던, 지연 로딩을 통해서 트랜잭션을 커밋하는 시점에 날리지 않고, 바로 SQL을 날리게 된다.)
  • em.persist 이후, id 값을 출력하는 로직이 있다면, select 쿼리는 날리지 않는다.
    • DB 내부적으로, insert 를 하면 id 값을 리턴하는 것을 JPA 에서 사용할 수 있도록 지원하기 때문이다.

SEQUENCE 전략

  • em.persist 를 하는 과정에서
    • call next value for MEMBER_SEQ 를 통해서, 데이터베이스 시퀀스 테이블에서 Id 값을 가져온다.
    • 이후 1차 캐시에 Id 와 엔터티를 저장한다.
  • IDENTITY 와 다르게 버퍼링이 가능하다.
@Entity
@SequenceGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        sequenceName = "MEMBER_SEQ",
        initialValue = 1, allocationSize = 1
)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
...
}

create sequence MEMBER_SEQ start with 1 increment by 1

 

그렇다면, 자꾸 시퀀스 테이블에 가는 것은 안좋다.

  • 미리 데이터베이스에서 allocationSize 만큼 당겨놓고, 메모리에서 한개씩 쓴다.
  • 여러 요청에도 동시성 이슈없이 수행된다.
  • allocationSize 수정을 통해서, DB 네트워크를 타는 횟수를 줄인다.
    • 50 이나, 100 정도가 적당하다.

TABLE 전략

@Entity
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        table = "MY_SEQUENCES",
        pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
}

create table MY_SEQUENCES (
       sequence_name varchar(255) not null,
        next_val bigint,
        primary key (sequence_name)
    )

시퀀스 전용 테이블이 생성되어있고, 다음 키 값 (next_val) 은 뭐가 되어야하는지 들어있다.

시퀀스 전략과 마찬가지로, allocationSize 수정을 통해서, DB 네트워크를 타는 횟수를 줄인다.

'강의 정리 > 자바 ORM 표준 JPA' 카테고리의 다른 글

6. 고급 매핑  (0) 2020.12.29
5. 다양한 연관관계 매핑  (0) 2020.12.28
4. 연관관계 매핑 기초  (0) 2020.12.27
2. 영속성 관리  (0) 2020.12.26
1. JPA 시작하기  (0) 2020.12.26