티스토리 뷰

JAVA/JPA

엔티티 매핑

최진영 2021. 8. 10. 16:08

@Entity

  • @Entity가 클래스단에 붙은 클래스는 JPA가 관리하는 Entity라고 지정할 수 있다.
  • JPA에서는 entity를 리플렉션으로 관리하기 때문에 항상 기본 생성자가 필수이다. 접근 제어자의 경우 publicprotected까지만 허용되며 보통은 protected를 많이 쓰는 추세이다.
  • final 클래스, enum 클래스, interface, inner 클래스 모두에 사용이 불가능 하며 필드에는 final 상수로 지정하면 안된다.

property

  1. name
    • JPA에서 사용할 entity의 이름을 지정할 수 있다.
    • default: class name
    • 가급적 default값을 사용하도록 하자. 동일한 네이밍의 entity 클래스를 사용할 경우에만 건드는 것을 추천.

@Table

  • entity와 매핑할 테이블을 직접 지정해줄 수 있다.

property

  1. name
    • 매핑할 테이블 이름
    • default: entity name (@Entity의 name을 지정하지 않았으면 물론 클래스 네임을 따라간다.)
  2. catalog
    • 데이터베이스 catalog 매핑
  3. schema
    • 데이터베이스 schema 매핑
  1. uniqueConstraints(DDL option)
    • DDL 생성 시에 유니크 제약 조건 생성용

 

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

 jpa는 존재하지 않은 스키마에 대해서 @Entity가 걸려있는 클래스의 정보를 가지고 자동으로 스키마를 생성해주기도 한다. DDL을 어플리케이션 시점에서 자동으로 생성해주며 데이터베이스별 방언이 달라도 각 데이터 베이스에 맞는 적절한 DDL을 생성해준다.

예시)
<property name="hibernate.hbm2ddl.auto" value="create" />

 물론 이런 자동 생성 기능은 개발 시에서만 사용을 해야하며 실제 운영 서버의 경우 아예 옵션을 끄거나 적당히 테이블을 다듬어서 사용해야 한다.

옵션 설명
create 기존 테이블 삭제 후 다시 생성 (drop + create)
create-drop create와 같지만 종료시점에 테이블을 drop (drop + create + drop)
update 변경분만 반영
validate 엔티티와 테이블이 정상 매핑되었는지만 확인
none 자동 생성 사용하지 않음

 앞서 이야기한 대로 운영 서버에는 절대로 create, create-drop, update를 사용하면 안되기 때문에 항상 유의해아한다. 이들은 개발 초기단계에서만 사용되어야 하며 운영서버는 항상 none을 사용하도록 하자.

  • 개발 초기 단계 : create, update
  • CI 서버 또는 초기화 상태로 자동화된 테스트를 진행하는 개발자 서버 : create, create-drop
  • 테스트 서버 : update, validate
  • 운영 서버 : validate, none

 

 아래에 설명할 @Column등과 같은 매핑어노테이션에서 제약조건을 추가할 수 있지만 말했다시피 DDL 생성기능 자체는 DDL을 자동 생성할 경우에만 사용되고 이후 JPA 실행 로직에는 영향을 주지 않으니 사용하지 않은 옵션은 제거하도록 하자!

 

매핑 어노테이션

어노테이션 설명
@Column 컬럼 매핑
@Temporal 날짜 타입 매핑
@Enumerated enum 타입 매핑
@Lob BLOB, CLOB 매핑
@Transient 특정 필드를 컬럼에 매핑하지 않음(매핑 무시)2

@Column

 필드 값들에 컬럼을 매핑하는데 주로 사용된다. 대부분의 필드 값들이 다 해당 어노테이션에 포함된다고 보면 된다.

속성 설명 기본값
name 필드와 매핑할 테이블의 컬럼 이름 객체의 필드 이름
insertable, updatable 등록, 변경 가능 여부 TRUE
nullable(DDL) null 값 허용 여부 설정  
unique(DDL) 유니트 제약 조건 설정  
columnDefinition(DDL) 직접 컬럼에 정보 입력  
length(DDL) 문자 길이 제약 조건, String type에만 사용 255
percision, scale(DDL) BigDecimal 타입에서 소수점 포함한 전체 자리(percision), 소수 자리수(scale)을 설정 percision=19, scale=2

 나머지는 사실 DDL 생성조건이기 때문에 넘어가고, insertable과 updatable을 조금 유의하면서 사용한다면 좋을 것 같다.

  • insertable : false 사용 시 데이터베이스에 저장되지 않음, 읽기전용 필드로 변환
  • updatable : false 사용 시 데이터베이스에 수정되지 않음

@Temporal

 날짜 Date 혹은 Calendar를 사용할 경우 이를 테이블과 매핑할 때 사용한다.

 요즘은 대부분 LocalDateLocalDateTime을 사용하기 떄문에 이를 사용한다며 생략해도 된다.

@Enumerated

 자바의 enum 타입을 매핑할 때 사용한다.

 두가지 옵션이 존재하는데,

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

 말 그대로 ORIDINAL은 enum의 순서를 데이터베이스에 저장하는 옵션이다.

public enum Role {
    USER, ADMIN
}

 다음과 같은 enum 클래스가 있을 때 각각 USER과 ADMIN이지만 이 둘의 순서는 0번째, 1번째 이기 때문에 해당 옵션을 사용했을 경우 실제 DB에는 0과 1로 저장이 된다.

 

 따라서 항상 enum의 목적은 순서가 아닌 그 네이밍이 필요하기 때문에 EnumType.STRING을 잊지말고 사용해주어야 한다.

@Lob

 데이터베이스의 BLOB과 CLOB 타입에 매핑하기 위해서 사용된다. varchar를 뛰어넘는 저장 타입

 지정할 수 있는 속성은 따로 없으며 필드 타입이 문자면 CLOB, 나머지는 BLOB으로 자동 매핑 된다.

  • CLOB : String, char[], java.sql.CLOB
  • BLOB : byte[], java.sql.BLOB

@Transient

데이터베이스와 매핑하지 않고 순수 필드로써만 사용하고 싶을 경우 해당 어노테이션을 사용한다.

@Transient
private String tmp;

 

 

기본 키 매핑

기본키 매핑을 하기 위한 어노테이션은 딱 두가지만 존재한다.

  • @Id
  • @GeneratedValue
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

모든 entity에는 @Id 어노테이션이 달린 기본키가 존재해야하고, 자동 생성을 설정할 때 @GeneratedValue 어노테이션을 사용한다.

 

IDENTITY strategy

  • 기본키 생성을 데이터베이스에 위임
  • 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다 (ex AUTO_INCREMENT)
  • AUTO_INCREMENT되기 때문에 db에 저장하는 시점에 밖에 id 값을 알 수가 없음. 따라서 JPA는 IDNETITY strategy의 경우 batch insert를 하지 않고 persist 시점에서 즉시 insert sql을 실행함.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
privaate Long id;

 

 

SEQUENCE strategy

  • 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트
  • 주로 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용한다.
@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;
  ...
}
속성 설명 기본값
name 식별자 생성기 이름 필수
sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름  
initialValue(DDL) 시퀀스 ddl을 생성할 때 처음 시작하는 수 지정 1
allocationSize 시퀀스 한번 호출에 증가하는 수 50
catalog, schema    

 allocationSize의 경우 한번 시퀀스를 호출할 때 증가하는 수를 말한다. 즉 한번 호출했을 때 50까지 호출을 하는 것이 default이며, 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 반드시 1로 설정해두어야 한다.

 

TABLE strategy

  • 키 생성 전용 테이블을 만들어서 데이터베이스 시퀀스처럼 사용하는 전략
  • 모든 데이터베이스에 적용할 수 있지만 성능상 테이블을 생성해서 직접 만들기 때문에 문제가 될 수 있다.
create table MY_SEQUENCES (
  sequence_name varchar(255) not null,
  next_val bigint,
  primary key (secuence_name)
)
@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;
  ...
}
속성 설명 기본값
name 식별자 생성기 이름 필수
table 키생성 테이블 명  
pkColumnName 시퀀스 컬럼 명  
valueColumnName 시퀀스값 컬럼 명 next_val
initialValue 초기값 0
allocationSize 시퀀스 한 번 호출에 증가하는 수 50
catalog, schema    
uniqueConstraints(DDL) 유니크 제약조건 설정 가능  

 

권장하는 식별자 전략

  • 기본키 제약 조건 : null이 아니어야 하고, 유일해야 하고, 변하면 안된다.
  • 자연키 중에서는 이를 완전히 만족시키는 자연키를 찾기 힘들기 때문에 대체키를 사용하자.
  • 권장 : Long 형 + 대체키 + 키 생성 전략 사용

'JAVA > JPA' 카테고리의 다른 글

JPA 모든 N+1 발생 케이스과 해결책  (0) 2021.11.23
연관관계 매핑 기초  (0) 2021.08.12
영속성 관리 - 내부 동작 방식  (0) 2021.08.09
JPA 소개 및 특징  (0) 2021.08.09
댓글
최근에 올라온 글
Total
Today
Yesterday