JPA

4장 엔티티 매핑

iksadnorth 2023. 8. 30. 19:58

해당 게시물은 책 '자바 ORM 표준 프로그래밍'을 읽고 작성했습니다.

👣 개요

해당 게시물은 객체를 엔티티로 선언하기 위해 매핑하는 방법에 대한 내용을 담고 있다.

 

👣 @Entity

JPA가 엔티티로서 사용할 클래스에 추가하는 어노테이션.
해당 클래스는 다음과 같은 조건을 가져야 한다.

  • public or protected의 기본 생성자
  • final 클래스, Enum, Interface, Inner 클래스가 아닌 클래스
  • final 필드가 아닌 필드를 가진 클래스

그리고 해당 어노테이션은 다음과 같은 속성을 가진다.

name
엔티티 이름을 지정.
기본값은 클래스명이다.
엔티티 이름은 다른 엔티티와 중복되면 안된다.

 

👣 @Table

엔티티와 매핑할 테이블을 지정한다.
해당 어노테이션은 다음과 같은 속성을 가진다.

  • name
    매핑할 테이블 이름. 기본값은 @Entity에서 매핑한 엔티티 이름이 된다.
  • catalog
    catalog 기능이 있는 DB에서 catalog를 매핑
  • schema
    schema 기능이 있는 DB에서 schema를 매핑한다.

 

👣 DB 스키마 자동 생성

JPA는 DML 뿐만 아니라 DDL 쿼리도 자동으로 생성한다.
해당 기능은 persistence.xml에 다음 속성을 추가하면 실행된다.

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

위 속성은 아래와 같은 선택지들이 있다.

create
기존 테이블을 삭제하고 새로 생성. = DROP + CREATE
주로 개발 초기 단계에서 사용함.

create-drop
create 속성에 추가로 App을 종료할 때, DROP을 수행 = DROP + CREATE + DROP
주로 자동화된 테스트 환경에서 사용함.

update
DB와 Entity 매핑 정보를 비교하며 변경 사항만 수정함.
주로 개발 초기 단계에서 사용함.

validate
DB와 Entity 매핑 정보를 비교하며 차이가 있다면 경고를 발생시키고 App 실행을 거부한다.
주로 운영 서버에서 사용함.

none
자동 생성 기능을 아예 사용하지 않는다.
주로 운영 서버에서 사용함.

 

👣 기본 키 매핑

@Id 어노테이션을 사용해서 기본 키가 되는 필드를 설정한다.
기본 키를 할당하는 방식은 벤더마다 다른데
예를 들어, Oracle에서는 시퀀스 방식으로 기본 키를 할당하고
MySQL은 Auto Increment 방식으로 할당한다.
기본 키 할당 전략은 @GeneratedValue 어노테이션의 속성을 이용해서 설정한다.

IDENTITY
기본 키 생성을 DB에 위임한다.
MySQL, PostgreSQL, SQL Server에서 사용가능한 방법이다.
해당 방법은 DB에 저장하고 나서야 ID값을 구할 수 있다.
따라서 이 경우엔 기본 키값을 가져오기 위한 추가적인 쿼리를 보낸다
하지만 Hibernate는 JDBC 3에 추가된 Statement.getGeneratedKeys()를 이용해서
저장과 동시에 생성된 키값을 얻어올 수 있다. 때문에 1번만 통신한다.
해당 방법은 키값을 얻기 위해 presist() 메서드 호출 즉시 쓰기 지연 SQL 저장소를 거치지 않고
곧바로 쿼리를 날린다.

SEQUENCE
DB 시퀀스를 사용해서 할당한다.
DB 자체에 시퀀스를 정의하는 부분이 있어서 굳이 엔티티를 저장하지 않고도 
중복없이 순차적으로 증가되는 숫자를 얻을 수 있다.
해당 방법은 presist() 메서드를 호출해도 곧바로 쿼리를 날리지 않아도 된다.
ORACLE, PostgreSQL, H2에서 사용가능한 방법이다.

// 시퀀스 생성
CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENTS BY 1;

시퀀스 역시 JPA로 만들어 낼 수 있고 그런 기능은 @SequenceGenerator에 의해 수행된다.

@Entity
@SequenceGenerator(
    name = "BOARD_SEQ_GEN",
    sequenceName = "BOARD_SEQ",
    initialValue=1, allocationSize=1
)
public class Board {
    @Id 
    @GeneratedValue(
        strage=GenerationType.SEQUENCE,
        generator="BOARD_SEQ_GEN"
    )
    private Long id;
    ...
}

TABLE
키 생성 테이블을 운용해서 할당한다.
시퀀스를 사용할 수 없는 DB도 별도의 테이블을 운용해 시퀀스마냥 사용하는 방식이다.
해당 방식은 테이블을 이용해서 할당하는 것이라 모든 DB에서 사용가능하다.

// 시퀀스 역할의 테이블 생성
CREATE TABLE custom_seq (
    sequence_name varchar(255) primary key,
    next_val bigint,
);

마찬가지로 @TableGenerator로 자동 DDL을 수행해준다.

@Entity
@TableGenerator(
    name = "BOARD_SEQ_GEN",
    table = "custom_seq",
    pkColumnValue = "BOARD_SEQ",
    initialValue=1, allocationSize=1
)
public class Board {
    @Id 
    @GeneratedValue(
        strage=GenerationType.SEQUENCE,
        generator="BOARD_SEQ_GEN"
    )
    private Long id;
    ...
}

 

👣 필드와 컬럼 매핑

@Column
객체 필드를 테이블 컬럼으로 매핑

  • name
    매핑할 테이블의 컬럼 이름
  • insertable
    기본값은 true. false로 설정 시, DB에 저장시 해당 필드는 저장하지 않는다.
  • updateble
    기본값은 true. false로 설정 시, DB에 해당 필드값을 수정하지 않는다.
  • table
    또다른 테이블에 해당 필드를 칼럼으로 매핑하고 싶을 때 사용.
  • precision, scale
    BigDecimal 타입에서 사용됨.
    precision은 소수점을 포함한 전체 자릿수를
    scale은 소수의 자릿수다.

@Enumerated
Enum 타입을 매핑할 때, 사용함.
EnumType.ORDINAL : enum 순서를 DB에 저장.
EnumType.STRING : enum 이름을 DB에 저장

@Temporal
날짜 타입[Date, Calendar]을 매핑할 때, 사용함.

@Lob
BLOB, CLOB 타입을 매핑할 때, 사용한다.

@Transient
해당 어노테이션이 적용된 필드는 DB에 매핑하지 않는다.
그저 객체로서 데이터를 조달하고 싶을 때, 사용한다.

@Access
JPA가 엔티티의 데이터에 접근하는 방식을 결정할 때, 사용함.
AccessType.FIELD : 필드값에 직접 접근한다. private 제어자가 있어도 접근가능.
기본적으로 해당 방법이 Default 값으로 지정된다. 따라서 생략해도 무방하다.
AccessType.PROPERTY: 필드값에 Getter로 접근한다.
Getter 메서드에 @Id 혹은 @Column을 적용해서 해당 Getter를 접근 메서드로 지정한다.
만약 @Id가 Getter 메서드에 표기된다면 생략해도 무방하다.

@Entity
@Access(AccessType.PROPERTY)
public class Member {
    private String id;
    private String name;
    
    @Id
    public String getId() {
        return this.id;
    }
    
    @Column
    public String getName() {
        return this.name;
    }
}

 

'JPA' 카테고리의 다른 글

6장 다양한 연관관계 매핑  (0) 2023.08.31
5장 연관관계 매핑 기초  (0) 2023.08.30
3장 영속성 관리  (0) 2023.08.27
2장 JPA 시작  (0) 2023.08.27
1장 JPA 소개  (0) 2023.08.27