본문 바로가기
JPA/자바 ORM 표준 JPA 프로그래밍

Chap.4 엔티티 매핑

by devwari 2021. 5. 17.

객체와 테이블 매핑: @Entity, @Table

기본 키 매핑: @Id

필드와 컬럼 매핑: @Column

연관관계 매핑: @ManyToOne, @JoinColumn

 

@Entity

- JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션 필수

- @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라 부름

- 기본 생성자는 필수 (파라미터가 없는 public 또는 protected 생성자)

: JPA가 엔티티 객체를 생성할 때 기본 생성자를 사용하므로 필요

- final 클래스, enum, interface, inner 클래스에는 사용할 수 없음

- 저장할 필드에 final 사용하면 안됨

- 속성: name

 

@Table

- 엔티티와 매핑할 테이블 지정, 생략하면 매핑한 엔티티 이름을 테이블 이름으로 사용

- 속성: name, catalog, schema, uniqueContraints (DDL)

 

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

- JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원함

- 클래스의 매핑 정보를 보면 어떤 테이블에 어떤 컬럼을 사용하는지 알 수 있음

- JPA는 이 매핑정보와 데이터베이스 방언을 사용해서 데이터베이스 스키마를 생성함

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

- 위 속성을 추가하면 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성함

- hibernate.hbm2ddl.auto 속성: create(drop + create), create-drop(drop + create + drop), update, validate, none (p.127 참고)

- hibernate.ejb.naming_strategy 소성을 사용하면 이름 매핑 전략 변경 가능

- @Column의 length, nullable 속성을 포함해서 이런 기능들은 단지 DDL을 자동 생성할 때만 사용되고 JPA 실행 로직에는 영향을 주지 않음. 스키마 자동 생성 기능을 사용하지 않고 직접 DDL 만든다면 사용할 이유 없지만 이 기능을 사용하면 애플리케이션 개발자가 엔티티만 보고도 손쉽게 다양한 제약 조건을 파악할 수 있는 장점이 있음

 

기본 키 매핑

- JPA가 제공하는 데이터베이스 기본 키 생성 전략: 직접 할당, 자동생성(IDENTITY, SEQUENCE, TABLE)

- 자동생성 전략이 다양한 이유는 데이터베이스 벤더마다 지원하는 방식이 다르기 때문

ex) 오라클은 시퀀스를 제공하지만 MySQL은 시퀀스를 제공하지 않음. 대신에 MySQL은 기본 키 값을 자동으로 채워주는 AUTO_INCREMENT 기능을 제공함

- 엔티티가 영속 상태가 되려면 식별자가 반드시 필요함. IDENTITY 식별자 생성 전략은 엔티티를 데이터베이스에 저장해야 식별자를 구할 수 있으므로 em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달됨. 따라서 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않음

- JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 @SequenceGenrator.allocationSize를 사용함

- AUTO 전략: 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략중 하나를 자동으로 선택함

ex) 오라클을 선택하면 SEQUENCE를, MySql을 선택하면 IDENTITY를 사용

- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 엔티티를 영속 상태로 만들려면 식별자 값이 반드시 있어야함

ex)

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long sn;

 

@Column

- 객체 필드를 테이블 컬럼에 매핑

- 속성: name, insertable, updatable, table, nullable(DDL), unique(DDL), columnDefinition(DDL), length(DDL), precision, scale(DDL) -> BigDecimal, BigInteger 타입에서 사용

- 자바 기본 타입일 때는 nullable 속성에 예외가 있음

ex)

int data1; // @Column 생략, 자바 기본 타입

data1 integer not null // 생성된 DDL

@Column

int data3; // @Column 사용, 자바 기본 타입

data3 integer // 생성된 DDL

 

@Enumerated

- 자바의 enum 타입을 매핑할 때 사용

- 속성 value

: public enum EnumType {
    ORDINAL, // enum 순서를 db에 저장, db에 저장되는 데이터 크기가 작음, 이미 저장된 enum의 순서를 변경할 수 없음, 기본값
    STRING; // enum 이름을 db에 저장, 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전함, db에 저장되는 데이터 크기가 ORDINAL에 비해서 큼

}

 

@Temporal

- 날짜 타입(java.util.Date, java.util.Calender)을 매핑할 때 사용함

- 속성 value

: public enum TemporalType {
    DATE, // 날짜, db date 타입과 매핑 (ex: 2013-10-11)
    TIME, // 시간, db time 타입과 매핑 (ex: 11:11:11)
    TIMESTAMP; // 날짜와 시간, db timestamp 타입과 매핑 (ex: 2013-10-11 11:11:11)

}

- 자바의 Date 타입에는 년월일 시분초가 있지만 db에는 date(날짜), time(시간), timestamp(날짜와 시간)라는 세 가지 타입이 별도로 존재함

- datetime: MySQL, timestamp: H2, 오라클, PostgreSQL

: datetime vs timestmap (ref. https://nesoy.github.io/articles/2020-02/mysql-datetime-timestamp)

1) timestamp은 time_zone에 의존함

2) 지원범위

datetime 1000-01-01 00:00:00부터 9999-12-31 23:59:59까지 지원

timestamp 1970-01-01 00:00:01부터 2038-01-19 03:14:07까지 지원, Index가 더 빠르게 생성됨

3) 컬럼 타입

datetime은 문자형, timestamp는 숫자형

4) 저장되는 공간

datetime은 8byte, timestamp는 4byte 저장공간을 차지함

 

@Lob

- 데이터베이스 BLOB, CLOB 타입과 매핑함

- 매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB

: CLOB: String, char[]

: BLOB: byte[]

 

@Trnsient

- 이 필드는 매핑하지 않음

- 데이터베이스에 저장하지 않고 조회하지도 않음

- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용함

ex)

    @Transient
    public static final String USERNAME_FOR_FIND_USERNAME = "FIND_USERNAME";

 

@Access

- JPA가 엔티티 데이터에 접근하는 방식을 지정함

- @Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식이 설정됨

- @Id가 필드에 있으므로 @Access(AccessType.FIELD)로 설정한 것과 같음 (@Id가 프로퍼티에 있을 때도 동일)

- 필드 접근 방식과 프로퍼티 접근 방식을 함께 사용할 수도 있음

public enum AccessType {

    /** Field-based access is used. */
    FIELD, // 필드에 직접 접근

    /** Property-based access is used. */
    PROPERTY // 접근자 Getter를 사용
}

ex) 

@Access(AccessType.PROPERTY)

public String getFullName() {

return firstName + lastName; // 회원 엔티티를 저장하면 회원 테이블의 FULLNAME 컬럼에 fistName + lastName의 결과가 저장됨

}

'JPA > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글

Chap.6 다양한 연관관계 매핑  (0) 2021.05.23
Chap.5 연관관계 매핑 기초  (0) 2021.05.19
Chap.3 영속성 관리  (0) 2021.05.10
Chap.2 JPA 시작  (0) 2021.05.10
Chap.1 JPA 소개  (0) 2021.05.10