4.6 기본 키 매핑
@Entity
public class Member {
@Id
@Column(name = "ID")
private String id;
◉ JPA가 제공하는 데이터베이스 기본 키 생성 전략
- 데이터베이스 벤더마다 기본 키 생성을 지원하는 방식이 다름
◉ 기본키 생성 전략 방식
- 직접 할당 : 기본 키를 어플리케이션이 직접 할당
- 자동 생성 : 대리 키 사용 방식
- INDENTITY : 기본 키 생성을 데이터베이스에 위임.
- SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당.
- TABLE : 키 생성 테이블을 사용한다.
◉ 기본키 생성 방법
- 기본 키를 직접 할당 :
@Id
만 사용 - 자동 생성 전략 사용 :
@GeneratedValue
추가 및 키 생성 전략 선택.
◉ 키 생성 전략 사용을 위한 속성 추가
<property name="hibernate.id.new_generator_mappings" value="true" />
4.6.1
// 기본 키 직접 할당
@Id
@Column(name = "id")
private String id;
@Id 적용 가능한 자바 타입
- 자바 기본형
- 자바 래퍼형
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
기본 키 할당하는 방법
Board board = new Board();
board.setId("id1"); //기본 키 직접 할당
em.persist(board);
4.6.2 IDENTITY 전략
IDENTITY는 기본 키 생성을 데이타베이스에 위임하는 전략.
주로 MySQL, PostgreSQL, SQL Server, DB2, H2에서 사용.
◉ MySQL의 AUTO_INCREMENT 기능
CREATE TABLE BOARD {
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
DATA VARCHAR(255)
};
INSERT INTO BOARD(DATA) VALUES('A');
INSERT INTO BOARD(DATA) VALUES('B');
BOARD 테이블 결과
ID | DATA |
---|---|
1 | A |
2 | B |
◉ IDENTITY 전략
- 데이터베이스에 값을 저장하고 나서야 기본 키 값을 구할 수 있을 때 사용.
em.persist()
호출시 INSERT SQL을 즉시 데이터베이스에 전달.- 식별자를 조회해서 엔티티의 식별자에 할당.
- 쓰기 지연이 동작하지 않는다.
@Entity
public class Professor {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private long salary;
...
}
4.6.3 SEQUENCE 전략
유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
주로 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용.
시퀀스 관련 SQL
CREATE TABLE BOARD (
ID BIGINT NOT NULL PRIMARY KEY,
DATA VARCHAR(255)
)
//시퀀스 생성
CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;
시퀀스 매핑 코드
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ",
initialValue = 1,
allocationSize = 1)
public class Board {
@Id
@GeneraedValue(strategy = GenerationType.SEQUNCE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
}
시퀀스 사용 코드
private static void logic(EntityManager em) {
Board board = new Board();
em.persist(board);
System.out.println("board.id = " + board.getId());
}
- 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회.
- 조회한 식별자를 엔티티에 할당.
- 엔티티를 영속성 컨텍스트에 저장.
- 트랜잭션 커밋.
- 플러시 - 데이터베이스에 저장.
주의
- SequenceGenerator.allocationSize 기본값이 50.
- 반드시 1로 설정.
TABLE 전략
키 생성 전용 테이블을 하나 만들고 여기에 이름과 값을 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략.
테이블을 사용하므로 모든 데이터베이스에 적용 할 수 있다.
TABLE 전략 키 생성 테이블
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key (sequence_name)
)
TABLE 전략 매핑 코드
@Entity
@TableGenerator(
name = "BOARD_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "BOARD_SEQ", allocationSize = 1)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
}
TABLE 전략 매핑 사용 코드
private static void logic(EntityManger em) {
Board board = new Board();
em.persist(board);
System.out.println("board.id = " + board.getId());
}
// 출력 : board.id = 1
- MY_SEQUENCES 테이블에 값이 없으면 JPA가 값을 INSERT
- 미리 넣어둘 필요가 없다.
시퀀스 대신에 테이블을 사용한다는 것만 제외하면 SEQUENCE 전략과 동일
4.6.5 AUTO 전략
GenerationType.AUTO는 선택한 데이터베이스 방언에 따라 INDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택.
AUTO 전략 매핑 코드
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
@GeneratedValue.strategy의 기본값은 AUTO.
장점
- 데이터베이스를 변경해도 코드를 수정할 필요가 없다.
- 키 생성 전략이 확정되지 않은 개발 초기 단계, 프로토타입 개발시 편리.
4.6.6 기본 키 매핑
테이블의 기본 키 선택 전략 2가지
- 자연 키
- 비지니스에 의미가 있는 키
- 주민등록번호, 이메일, 전화번호
- 대리 키
- 비지니스와 관련 없는 임의로 만들어진 키, 대체 키.
- 오라클 시퀀스, auto_increment, 키생성 테이블
미래까지 충족하는 자연 키를 찾기 쉽지 않다.
JPA는 모든 엔티티에 일관된 방식으로 대리 키 사용을 권장