결론
복합키 중 자동증가하는 값(ID)이 있으면
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="gen1")
이렇게 SEQUENCE 타입을 써야 한다 !!
(GenerationType.IDENTITY로 지정 x)
문제발견
프로젝트를 진행하며 스프링부트로 백엔드를 구현하고 있었다.
(ID) (AnotherKey)
2개를 엮어 복합키로 사용하고자 한다!
그런데
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "memberId", nullable = false)
Long memberId;
Identity Generation이 복합키를 지원하지 않는다!
해결방법
public class Member extends BaseTimeEntity {
@SequenceGenerator( // 제너레이터 정의
name = "gen1", // JPA에서 사용할 제너레이터 이름
sequenceName = "gen1", // DB 시퀀스 이름
allocationSize = 1 // 증가 간격
)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="gen1") // 제너레이터(gen1) 연결
@Column(name = "ID", nullable = false)
Long memberId;
@Id
@Column(name = "AnotherKey", nullable = false)
String anotherKey;
ID값 생성 방식을 SEQUENCE로 바꿔줬다!
왜 되는가?
@GeneratedValue의 키본키 생성 방식
IDENTITY | 기본키 생성을 데이터베이스에 위임 | |
SEQUENCE | 기본키 생성을 시퀀스에서 담당 (@SequenceGenerator시퀀스 생성, 매핑 필요) |
|
TABLE | 기본키 생성을 테이블에서 담당 (@TablleGenerator로 테이블 생성, 매핑 필요) |
|
AUTO (기본) | IDENTITY, SEQUENCE, TABLE 중 하나 자동선택 |
Identity 의 키 생성 방식
1. Database에 INSERT할 데이터를 먼저 넣음 (키는 NULL)
키 | 데이터 |
NULL | (넣을 데이터값) |
현재 데이터베이스
🙋♀️ 키는 알아서 DB에서 만들어줘~
(키 생성은 DB에 일임)
2. 엔티티 ➔ 영속성 컨텍스트로 등록 시 INSERT쿼리 날림
🙋♀️이때, DB에 조회해 키를 가져옴 (DB에서 생성한 키)
키 | 데이터 |
NULL이 아닌값 | (넣을 데이터값) |
현재 데이터베이스
이때, 복합키의 경우에는,
즉 예를 들어
ID | 다른 키 값 |
1 | ABCD |
라고 한다면,
스프링부트는 1, ABCD 중에 어떤 게 ID값인지 모른다.
(스프링부트 구현 상 그렇게 해둔 듯)
그래서 INSERT 쿼리를 날릴 때 ID를 채우지 못하고 실패하는 것이다.
Sequence 의 키 생성 방식
Oracle, PostgreSQL, DB2, D2 DB에서 지원하는 전략인 Sequence의 경우
연속 숫자를 생성하도록 Sequence를 생성하고,
이것을 이용해 ID를 생성하도록 하는 방식이다
public class Member extends BaseTimeEntity {
@SequenceGenerator( // 제너레이터 정의
name = "gen1", // JPA에서 사용할 제너레이터 이름
sequenceName = "gen1", // DB 시퀀스 이름
allocationSize = 1 // 증가 간격
)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="gen1") // 제너레이터(gen1) 연결
@Column(name = "ID", nullable = false)
Long memberId;
나의 경우,
1씩 증가하는 sequence를 생성하고
이를 ID 생성 방식에 적용한 것이다
참고로
@SequenceGenerator로 만든 Sequence
MINVALUE, MAXVALUE, NOCYCLE, START WITH, INCREASE 등 다양한 옵션을 사용할 수 있다
(더 많은 option에 대한 정보는 이 글에서 볼 수 있다)
참고
- @Generated 기본키 생성 방식 https://velog.io/@tritny6516/JPA-기본키Primary-Key-매핑-Id-GeneratedValue
- IDENTITY 기본키 생성 방식 https://gmlwjd9405.github.io/2019/08/12/primary-key-mapping.html#google_vignette
'백엔드' 카테고리의 다른 글
[DB 해킹] MySQL DB 털린 썰 풉니다 (RECOVER_YOUR_DATA) (0) | 2024.12.23 |
---|---|
MySQL 연결 - characterEncoding=utf8mb4 쓰지 마세요! (0) | 2024.12.12 |
[스프링부트] Soft delete 구현 (1) | 2024.12.09 |
[스프링부트] Spring Batch와 적용방법 (3) | 2024.12.09 |
MySQL 한글 (인코딩) 에러 났을 때 해결방법 (0) | 2024.12.09 |