본문 바로가기

SpringFramework/JPA

JPA - 엔티티 매핑

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

- 기본 키 매핑: @Id

- 필드와 컬럼 매핑: @Column

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

@Entity

속성 기능 기본값
name JPA에서 사용할 Entity 이름을 지정. 설정하지 않으면 Class명을 그대로 사용한다 (ex) User class -> "User")

@Entity 사용시 주의사항

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

  => 실제로 Entity Class에서 생성자를 생략해도 Java에서는 기본생성자를 만들어주기 때문에 오류가 발생하지는 않음.

  => JPA가 객체 생성시에 기본 생성자를 사용하기 때문

- final, enum, interface, inner Class에서는 사용할 수 없음

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

@Table

: Entity와 매핑할 테이블을 지정한다

속성 기능 기본값
name 매핑할 테이블명 Entity Name
catalog catalog 기능이 있는 데이터베이스에서 catalog를 매핑  
schema schema 기능이 있는 데이터베이스에서 schema를 매핑  
uniqueConstraints (DDL) DDL 생성시에 unique 제약조건을 만든다. 2개 이상의 복합 unique 제약조건도 생성가능.
- 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용 (그러나 이방법은 비추천)
 

@Id

기본키 할당. JPA에서 데이터를 제어할 식별자에 해당한다. 보통 테이블의 기본키(PK)에 매핑해주는 경우가 많다

- 키(key)생성 전략

1] 직접생성

    ex) user.setId(1);

    @Id 적용가능 자바타입

    - 자바 기본형 (char, int, long, double 등...)

    - 자바 Wrapper형 (Integer, Long, Double 등...)

    - String

    - java.util.Date, java.sql.Date

    - java.math.BigDecimal, java.math.BigInteger

  => 보통은 직접 할당보다는 자동생성 할당전략으로 많이 사용한다.

 

2] 자동생성

- AUTO(default): JPA 구현체(스프링부트에서는 Hibernate)가 생성 방식을 결정(JPA에게 위임한다)

=> Hibernate 5.0 부터는 기본 전략이 TABLE, 그이전에는 IDENTITY 방식이다

 

- IDENTITY: 사용하는 데이터베이스가 키 생성을 결정(= 데이터베이스에 위임)한다. MySQL이나 MariaDB는 기본기 자동생성 Auto-Increment 방식을 사용한다

    => 식별자 생성 전략은 엔티티가 데이터베이스에 저장되어야 식별자를 구분할 수 있으므로, 트랜잭션을 지원하는 쓰기 지연이 동작하지 않음 (데이터 저장후 식별자에 할당)

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;

@Getter
@Setter
@Entity
@Table(name = "user")
public class UserEntity {
    @Id
    @Column(name="user_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    
    private String userName;
    
    private Integer userAge;
}

 

- SEQUENCE: 데이터베이스의 sequence를 이용해서 key를 생성한다. @SequenceGenerator와 함께 사용

    => 시퀸스 생성기를 통해 식별자가 만들어지므로, 식별자 할당후 데이터를 저장)

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;

@Getter
@Setter
@Entity
@SequenceGenerator(
        name = "user_seq_generator",
        sequenceName = "user_seq",
        initialValue = 1, allocationSize = 50
)
@Table(name = "user")
public class UserEntity {
    @Id
    @Column(name="user_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq_generator")
    // @SequenceGenerator는 여기에 놓아도 됨
    private Long userId;
    
    private String userName;
    
    private Integer userAge;
}

@SequenceGenerator 속성

속성 기능 기본값
name 식별자 생성기 이름 required
sequenceName 데이터베이스에 등록되어 있는 시퀸스 이름 hibernate_sequence
initialValue DDL 생성시에만 사용됨. 시퀸스 DDL을 생성할 때 처음 시작하는 수를 지정 1
allocationSize 시퀸스 한번 호출에 증가하는 수

(?) default가 50인이유 => 식별자를 구하기 위해 시퀸스를 조회할 때 DB를 호출한다. 만약 가져오는 수치가 1이라면, 1씩 증가할떄마다 DB를 호출하고, 50이라면 1~50까지 미리 가져와서 메모리에 할당시켜두고 쓰다가, 50까지 다 사용하면 그때 DB를 호출한다. SEQUENCE 성능 최적화와 관련된다
50

 

- TABLE: 키 생성 전용 테이블을 생성하여 키생성. @TableGenerator와 함께 사용

 

SEQUENCE 테이블을 생성해야한다.

CRATE TABLE user_sequence_table (
    seq_name varchar(255) NOT NULL,
    next_val BIGINT,
    PRIMARY KEY (seq_name)
);
/*
테이블 데이터
컬럼명 seq_name    | next_val
     user_seq    | 3
     member_seq  | 121
     product_seq | 211
*/
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;

@Getter
@Setter
@Entity
@TableGenerator(
        name = "user_table_seq_generator",
        table = "user_sequence_table", // 키생성 테이블명
        pkColumnName = "seq_name" // 시퀸스 컬럼명
        pkColumnValue = "user_seq", // 키로 사용할 값 이름
        valueColumnName = "next_val" // 시퀸스 값 컬럼명
        allocationSize = 1
)
@Table(name = "user")
public class UserEntity {
    @Id
    @Column(name="user_id")
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "user_table_seq_generator")
    private Long userId;
    
    private String userName;
    
    private Integer userAge;
}

 

@TableGenerator 속성

속성 기능 기본값
name 식별자 생성기 이름 required
table 키생성 테이블명 hibernate_sequences
pkColumnName 시퀸스 컬럼명 sequence_name
valueColumnName 시퀸스 값 컬럼명 next_val
pkColumnValue 키로 사용할 값 이름 엔티티 이름
initialValue 초기 값, 마지막으로 생성된 값이 기준 0
allocationSize 시퀸스 한번 호출에 증가하는 수
=> SEQUENCE전략과 마찬가지로 최적화와 관련이 있다. (DB 통신 횟수)
50
usiqueConstraints(DDL) DDL 생성시에 unique 제약조건을 만든다. 2개 이상의 복합 unique 제약조건도 생성가능.
- 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들때만 사용 (그러나 이방법은 비추천)
 

컬럼

@Column: 컬럼을 매핑한다.

  - name: 필드와 매핑할 테이블의 컬럼명

 

@Enumerated: 자바의 enum 타입을 매핑한다

  - value

    EnumType.ORDINAL(default): enum 순서를 데이터베이스에 저장

    EnumType.STRING: enum 이름을 데이터베이스에 저장

    ex)

    public enum STATUS {

        READY, START, END

    } // enum 정의

    ----

    @Enumerated(EnumType.ORDINAL)

    private STATUS status; // 어노테이션 정의

    user.setStatus(STATUS.READY); -> 0으로 저장

    ----

    @Enumerated(EnumType.STRING)

    user.setStatus(STATUS.READY) -> "READY" 문자열이 저장

 

@Temporal: 날짜 타입을 매핑한다 (java.util.Date, java.util.Calendar)

  - value

    TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑

    TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑

    TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑

 

@Lob: BLOB(byte[], java.sql.BLOB), CLOB(String, char[], java.sql.CLOB) 타입을 매핑한다

 

@Transient: 특정 필드를 데이터베이스에 매핑하지 않는다

  데이터베이스에 저장하지도않고 조회도 하지 않는다. 객체에 임시로 어떤 값을 보관하고 싶을 때 사용

 

@Access: JPA가 엔티티에 접근하는 방식을 지정한다

  AccessType.FIELD: 필드에 직접 접근가능 (private라도 접근이 가능)

  AccessType.PROPERTY: 접근자 Getter를 사용

@Entity
public class MyName {
    @Id
    private String id;
    
    @Transient
    priate String firstName;
    
    @Transient
    private String lastName;
    
    @Access(AccessType.PROPERTY)
    public String getFullName() {
        return firstName + lastName;
    }
}

참고자료

- https://jojoldu.tistory.com/295

- 서적 - 자바 ORM 표준 JPA 프로그래밍 제 4장 - 김영한 지음

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

JPA - 값타입  (0) 2021.11.16
JPA - 연관관계 고급매핑  (0) 2021.11.15
JPA - 연관관계  (0) 2021.11.14
JPA - 영속성 컨텍스트  (0) 2021.11.03
JPA - 기본 개념 및 내용정리  (0) 2021.02.05