JPA의 PK 등록 전략
DB : MySQL
package Study.Board.board;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import java.time.LocalDateTime;
@Getter
@Entity
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id @GeneratedValue // PK 생성 전략에 대하여
@Column(name = "board_id")
private Long id;
private String title;
private String content;
private String password;
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
private LocalDateTime deletedAt;
public Board(String password, String content, String title) {
this.password = password;
this.content = content;
this.title = title;
createdAt = LocalDateTime.now();
}
}
1. @GeneratedValue를 사용하지 않는 경우
@Id
@Column(name = "board_id")
private Long id;
@GeneratedValue를 사용하지 않으면 아래처럼 직접 개발자가 setter 또는 생성자 방식으로 PK를 설정해야 한다.
Board board = new Board();
board.setId(1L); // 직접 ID(PK) 설정 필요
em.persist(board);
2. @GeneratedValue(strategy = GenerationType.IDENTITY)
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id")
private Long id;
PK 생성을 DB에 위임하는 전략이다.
MySQL, PostgreSQL에서 주로 활용한다.
사용 시 Auto Increment가 적용된다.
DB에 값이 insert될 때 PK를 비우고 insert 시 DB가 순서대로 PK를 할당한다.
DB에 저장 후 PK 조회가 가능하다. DB 저장 전에 PK 조회 불가
em.persist() 호출 시점에 즉시 INSERT 쿼리가 실행되고, 그 직후 DB가 생성한 ID를 조회하여 영속성 컨텍스트 내의 객체에 채운다.
단점 : 쓰기 지연 활용 불가, em.persist 시 쓰기 지연이 아니라 즉시 쿼리를 전달한다.
실제 출력되는 쿼리
[Hibernate]
drop table if exists board
[Hibernate]
create table board (
board_id bigint not null auto_increment,
created_at datetime(6),
deleted_at datetime(6),
updated_at datetime(6),
content varchar(255),
password varchar(255),
title varchar(255),
primary key (board_id)
) engine=InnoDB
3. @GeneratedValue(strategy = GenerationType.SEQUENCE)
4. @GeneratedValue(strategy = GenerationType.TABLE)
1. 시퀀스 테이블 = 번호표(시퀀스) 생성 기계
MySQL의 AUTO_INCREMENT는 테이블 자체에 번호 생성 기능이 붙어 있는 방식이지만,
하이버네이트의 기본(AUTO) 설정은 별도의 '번호표(시퀀스) 전용 테이블'을 만들어 관리한다.
board_seq 테이블: 번호표를 보관하는 기계
values ( 1 ): "이제부터 번호는 1번부터 발행한다!"라고 기계를 초기 세팅
2. 작동 원리
새 게시글을 저장하려고 하면, 스프링은 board 테이블로 바로 가지 X
먼저 board_seq 테이블에 가서 "다음 번호 몇 번이야?"라고 물어보고 번호를 하나 가져간다.
가져온 번호를 board_id에 할당한 뒤, 비로소 board 테이블에 데이터를 넣는다.
5. @GeneratedValue
@GeneratedValue만 쓴다면 GenerationType.AUTO가 적용되며, 각 DB에 적절한 전략을 자동으로 정한다.
예시 : @GeneratedValue + MySQL 조합 : TABLE 전략 사용
@GeneratedValue, ddl auto : create 일 때 출력되는 쿼리
@Id @GeneratedValue
@Column(name = "board_id")
private Long id;
[Hibernate]
drop table if exists board
[Hibernate]
drop table if exists board_seq
[Hibernate]
create table board (
board_id bigint not null,
created_at datetime(6),
deleted_at datetime(6),
updated_at datetime(6),
content varchar(255),
password varchar(255),
title varchar(255),
primary key (board_id)
) engine=InnoDB
[Hibernate]
create table board_seq (
next_val bigint
) engine=InnoDB
[Hibernate]
insert into board_seq values ( 1 )
Auto Increment가 동작하지 않는다.
[Hibernate]
create table board_seq (
next_val bigint
) engine=InnoDB
[Hibernate]
insert into board_seq values ( 1 )
'Java & Spring > JPA' 카테고리의 다른 글
| [Spring] JPA 5 (1) | 2026.03.03 |
|---|---|
| [Spring] JPA 변경 감지 (0) | 2026.02.13 |
| [Spring] JPA 3 (0) | 2026.02.05 |
| [Spring] JPA 2 (0) | 2026.01.28 |
| [Spring] JPA 1 (0) | 2026.01.20 |