🌿SPRING/🍀공부 [SPRING]

[SPRING] [JPA] 기본 키 매핑 @GeneratedValue

디카페인라떼 2022. 8. 31. 12:14
더보기

개인 프로젝트에서 DB id 들이

사용자 1,2,3,4..

게시글 1,2,3,4..

댓글 1,2,3,4..

 

이런 식으로 하고 싶었는데 내가 구현한 거는

 

사용자 1,4..

게시글 2,5,6..

댓글 3,7,8..

 

이런 식이라 찾아보니 기본키 매핑의 문제였다... ㅎㅎㅎㅎㅎㅎㅎ

 

@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

<기본키를 할당하는 방법>

  • 직접할당 : 기본 키를 어플리케이션에서 직접 할당 해주는 방법 (application에서 생성)
    • @Id만 사용하면 됨
  • 자동생성 : 데이터베이스가 자동으로 할당해주는 방법 (db가 생성)
    • @Id와 @GeneratedValue 사용
    • 여러가지로 나뉨!

<자동 생성의 종류>  @GeneratedValue(strategy = GenerationType. Xxx

 

  • IDENTITY
    • 기본 키 생성을 데이터베이스에 위임. MySQL에서 많이 씀.
  • SEQUENCE
    • 데이터 베이스 오브젝트를 이용. 데이터베이스 시퀀스를 사용해서 기본 키를 할당. 
    • @SequenceGenerator 필요.ORACLE에서 많이 사용.
  • TABLE
    • 별도의 키 생성 테이블을 사용. 모든 DB에서 사용가능.
    • @TableGenerator 필요. ddl-auto가 아닌 경우, 별도의 Table을 생성해야 합니다.
  • AUTO
    • 방언에 따라 자동으로 기본 값으로 지정.

IDENTITY
// IDENTITY 매핑 코드
@Entity
public class Member{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long id;
 ...
 }
  • 데이터베이스에 값을 저장하고 나서야 기본 키 값을 구할 수 있음.
    • DB에 INSERT문이 실행된 후 ID값을 알 수 있으므로 em.persist() 하는 시점에 필요한 ID 값이 없다
    • 따라서 예외적으로 persist() 하는 시점에 즉시 INSERT문이 실행되어 DB에서 식별자 조회
    • 엔티티가 영속 상태가 되기 위해서는 식별자가 필요합니다. IDENTITY 전략의 경우, 식별자 생성을 데이터 베이스에 저장해야 구할 수 있으므로 em.persist()를 호출하여 객체를 영속성 상태로 만드는 순간 INSERT SQL이 호출됩니다. 따라서, 이 전략은 쓰기 지연이 동작하지 않습니다.

 

SEQUENCE
// 시퀀스 매핑 코드
@Entity
@SequenceGenerator(
 name = "MEMBER_SEQ_GENERATOR",
 sequenceName = "MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
 initialValue = 1, allocationSize = 1)
public class Member{

 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE,
                 generator = "MEMBER_SEQ_GENERATOR")
 private Long id;
 ...
 }

 

데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트입니다. SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성합니다. 이 전략은 시퀀스를 지원하는 오라클, PostgreSQL, DB2, H2 데이터베이스에 사용됩니다

 

  • 유일한 값을 순서대로 생성하는 시퀀스 오브젝트를 활용 (예: 오라클 시퀀스)
    • persist() 할 때 시퀀스 DB에서 ID값만 불러와서 영속성 컨텍스트에 엔티티 영속
    • 따라서 IDENTITY와 다르게 쿼리들을 버퍼링했다가 커밋할 때 한번에 전달 가능
    • 그럼에도 영속할 때마다 DB와 통신한다는 성능 이슈 때문에 allocationSize = 50 이 기본값
      • 미리 DB에 50까지 만들어 놓고 ID가 50까지 증가하는 동안은 그 값을 메모리에서 불러옴
      • ID값을 DB를 통해 불러오는 경우가 획기적으로 줄며, 동시성 문제도 해결 가능
  • IDENTITY와의 차이점은 IDENTITY의 경우, 영속성 컨텍스트에 저장하기 위해서 INSERT를 바로 날린다는 점입니다.
TABLE
// TABLE 전략 매핑 코드
@Entity
@TableGenerator(
 name = "BOARD_SEQ_GENERATOR",
 table = "MY_SEQUENCES",
 pkColumnValue = "BOARD_SEQ", allocationSize = 1)
public class Member {

 @Id
 @GeneratedValue(strategy = GenerationType.TABLE,
                 generator = "BOARD_SEQ_GENERATOR")
 private Long id;
 ...
 }

 

  • SEQUENCE 전략에서 @SequenceGenerator를 사용한 것처럼, Table은 @TableGenerator를 사용합니다.
  • TABLE 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략입니다.
    • 장점: 모든 데이터베이스에 적용 가능
    • 단점: 성능이 떨어짐