코딩공작소

JPA 프로그래밍 학습 정리 (2) - 엔티티 매핑 본문

어플리케이션개발/JPA

JPA 프로그래밍 학습 정리 (2) - 엔티티 매핑

안잡아모찌 2024. 1. 7. 16:42
엔티티 매핑

JPA에서 가장 중요한 것은 엔티티와 테이블의 정확한 매핑이다. 그러므로, 매핑 어노테이션을 숙지해야한다.

  • 객체와 테이블 매핑 : @Entity, @Table
  • 기본 키 매핑 : @Id
  • 필드와 컬럼 매핑 : @Column
  • 연관관계 매핑 : @ManyToOne, @JoinColumn
@Entity

기본 생성자가 필수다. 한 개 이상의 임의 생성자를 만들었다면 기본 생성자를 직접 만들어야한다.
@Table

1
2
3
4
5
@Entity
@Table(name = "MEMBER")
public class Member {
    ...
}
cs

persistence.xml 파일의 property 속성을 통해 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생상할 수 있다.
하지만 오직 개발서버나 개발단계에서만 사용해야 한다.

<property name = "javax.persistence.schema-generation.database.action"
value = "drop-and-create"/>

※ 기본 키 매핑

직접할당   기본 키를 애플리케이션에 직접 할당
자동생성 IDENTITY 데이터베이스에 위임
SEQUENCE 시퀀스를 사용해 기본 키 할당
TABLE 키 생성 테이블을 생성해서 할당

→ persistence.xml > hibernate.id.new_generator_mappings = true 를 설정해줘야 키 생성 전략 사용가능

● 기본키 직접 할당
@Id 어노테이션을 통해 직접 할당

1
2
3
4
5
6
7
8
9
10
11
12
// 적용 가능 자바타입
자바 기본형
자바 래퍼(Wrapper)형
String
java.util.Date
java.sql.Date
java.math.BigDecimal
java.math.BigInteger
 
Board board = new Board();
board.setId("id1"); // 기본 키 직접 할당
em.persist(board);
cs


● IDENTITY 전략
기본 키 생성을 데이터베이스에 위임한다.
AUTO_INCREMENT 기능

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE BOARD (
    ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    DATA VARCHAR(255)
);
 
 
@Entity
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    ...
}
cs

이 방식은 데이터베이스에 값을 저장하고 나서야 기본 키 값을 알 수 있다.
엔티티가 영속 상태가 되려면 반드시 식별자가 필요하다. 하지만 이 전략의 경우 데이터베이스에 저장해야 식별자 값을 알 수 있으므로 em.persist()를 호출하는 즉시 INSERT구문이 실행된다. 따라서 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.



● SEQUENCE 전략
유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE TABLE BOARD (
    ID BIGINT NOT NULL PRIMARY KEY,
    DATA VARCHAR(255)
);
 
CRAETE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;
 
 
@Entity
@SequenceGenerator(
    name = "BOARD_SEQ_GENERATOR",
    sequenceName = "BOARD_SEQ"// 매핑할 DB 시퀀스 이름
    initialValue = 1, allocationSize = 1)
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
                    generator = "BOARD_SEQ_GENERATOR")
    private Long id;
    ...
}
cs

이 전략은 em.persist()를 호출할 때 먼저 DB 시퀀스를 사용해 식별자를 조회한다. 그 후, 엔티티에 할당 한 후에 영속성 컨텍스트에 저장한다. 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.

@SequenceGenerator 전략은 1. 식별자 조회 2. 저장 의 과정을 거치므로 데이터베이스와 2번 통신한다. 이에 대한 최적화의 방법으로 속성 값 allocationSize를 50으로 설정한다. hibernate.id.new_generator_mappings 속성을 true로 설정해야하며, 해당 방식을 통하면 시퀀스를 한번에 50씩 증가시킨 후에, 1~50까지는 메모리에서 식별자를 할당하는 식으로 최적화하게 된다.



● TABLE 전략
키 생성 전용 테이블을 하나 만들고 위의 데이터베이스 시퀀스를 흉내내는 전략이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create table MY_SEQUENCES (
    sequence_name varchar(255) not null,
    next_val bigint,
    primary key ( sequence_name )
)
 
 
@Entity
@TableGenerator(
    name = "BOARD_SEQ_GENERATOR",
    table = "MY_SEQUENCES",
    pkColumnValue = "BOADRD_SEQ", allocationSize = 1)
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,
    generator = "BOARD_SEQ_GENERATOR")
    private Long id;
    ...
}
cs

 

내부 작동방식은 위의 SEQUENCE전략과 동일하다.

@Column
객체 필드에 테이블 컬럼을 매핑한다. 주로 name, nullable 속성이 사용된다.
@Enumerated
1
2
3
4
5
6
7
8
enum RoleType {
    ADMIN, USER
}
 
@Enumerated(EnumType.STRING)
private RoleType roleType;
 
member.setRoleType(RoleType.ADMIN); // DB에 문자 ADMIN으로 저장된다.​
cs
EnumType에는 ORIDINAL, STRING 두 개의 타입이 있는데 STRING 타입의 사용을 권장한다.
@Temporal
DATE, TIME, TIMESTAMP 3가지의 속성 유형을 가지고 있다. 
각각 날짜, 시간, 날짜와 시간 이다.
@Lob
CLOB, BLOB 두 가지의 속성이 있다.
@Transient
객체에 임시로 어떤 값을 보관하고 싶을 때 사용한다. 매핑은 하지 않는다.

@Access
JPA가 엔티티 데이터에 접근하는 방식을 지정한다. 필드 접근, 프로퍼티 접근 두가지의 방법이 존재한다. 필드 접근은 직접 접근하는 방식이며 프로퍼티 접근은 접근자(Getter)를 이용해서 접근하는 것이다.