GeneratedValue 그리고 복합키

Panda·2022년 3월 30일
0

Spring

목록 보기
16/42

프로젝트를 진행하다가 @GenerateValue 관련으로 문제를 겪어서
제대로 이해할겸 공부를 해봤습니다.

GeneratedValue 란?

데이터베이스에서 PK 설정 중에 auto_increment 라고
레코드가 추가될 때 마다 자동으로 pk 값을 증가시켜주는 옵션이 있는데

JPA에서는 기본키를 자동으로 생성해주는 @GeneratedValue 가 있습니다.

@Id@GeneratedValue를 같이 사용을 해야 합니다.
@GeneratedValue 에는 4가지 종류가 있는 한번 알아봅시다.

IDENTITY

@GeneratedValue(strategy = GenerationType.IDENTITY)

기본키 생성을 데이터베이스에게 위임하는 방식으로 id값을 따로 할당하지 않아도
데이터베이스가 자동으로 AUTO_INCREMENT를 하여 기본키를 생성해줍니다.

시점
em.persist() 시점에 쓰기 지연을 하지않고 바로 쿼리를 DB에 날려 데이터를 등록하고 식별자를 리턴받습니다.

주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다고 하더라고요. (예: MySQL의 AUTO_ INCREMENT)

보통은 이걸로 많이 사용하시더라고요

SEQUENCE

@GeneratedValue(strategy = GenerationType.SEQUNCE)

데이터 베이스의 Sequence Object를 사용하여 데이터베이스가 자동으로 기본키를 생성해준다.
@SequenceGenerator 어노테이션이 필요합니다.

@Entity
@SequenceGenerator(
	name = "USER_PK_SEQUENCE",
    sequenceName = "USER_PK_SEQ",
    initailValue = 1,
    allocationSize = 50
)
public class UserEntity() {		
	@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USER_PK_SEQUENCE")
    private Long id;
       
    private String name;
            
}
  • name : 식별기 생성자 이름
  • sequenceName : 데이터베이스에 등록되어 있는 시퀀스 이름
  • initailValue : DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정
  • allocationSize : 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨)
    데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값 을 반드시 1로 설정해야 합니다.

제가 시퀀스 규칙을 직접 정의하여 해당 규칙대로 PK값이 증가합니다.

시점
em.persist() 시점에 시퀀스를 조회하는 쿼리를 DB에 날려 시퀀스의 nextValue를 받고 영속성 컨텍스트에 등록합니다.

오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용한다고 합니다.

TABLE

@GeneratedValue(strategy = GenerationType.TABLE)

키를 생성하는 테이블을 사용하는 방법으로 SEQUENCE 방법과 매우 유사합니다.
@TableGenerator 어노테이션이 필요합니다.

@Entity
@TableGenerator(
	name = "USER_PK_TABLE",
    table = "USER_PK_SEQ",
    pkColumnValue = "USER_SEQ",
    allocationSize = 1
)
public class PkEx() {

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

키 생성 전용 테이블을 만들어서 데이터베이스 시퀀스 전략을 따라합니다.
장점은 모든 데이터베이스에 적용은 되는데
성능이 영...

성능떄문에 별로 안쓴다고 합니다. ㅋㅋㅋ

Auto

@GeneratedValue(strategy = GenerationType.AUTO)
기본 설정 값으로 각 데이터베이스에 따라 기본키를 자동으로 생성합니다.
(JPA 구현체가 자동으로 생성 전략을 고름)

복합키에서 GeneratedValue

프로젝트를 진행하다가 복합키가 설정된 Entity에서 GeneratedValue IDENTITY 방식을 사용했더니 아래와 같은 에러가 발생했다...

org.springframework.orm.jpa.JpaSystemException: Could not set field 
value [POST_INSERT_INDICATOR] value by reflection

먼저 해결방법 부터 쉽게 말하자면
복합키와 @EmbeddedId에서는 @GeneratedValue를 못 쓴다고 합니다.
호호호호...

근데 아무것도 몰랐을 떄는
@GeneratedValue(strategy = GenerationType.AUTO)
해서 돌아가서 돌아가는 줄 알았는데
실제로 id값을 확인 해보면 id값이 null로 표시된다.
(근데 대체 왜 DB에 저장이 되는거지???)

느낀 점

최대한 안전하게 데이터베이스를 설계하려면 복합키보다는
대표ID(PK) 값을 설정해주는 것이 낫다고 하더라고요

복합키를 구성할 떄는
특정 데이터를 식별하는 게 의미가 없는 도메인 일때 구성해준다고 하더라고요.
예) 걸음거리 기록 저장.

복합키는 대표ID 에 비해서는 자원적인 성능도 그렇고
Unique 하게 이루어지게 만들어야 하기때문에
생각할 거리가 많아지는 것 같습니다.

진짜 공부할수록 그리고 프로젝트 할 수록
JPA 랑 DB에 대해서 1도 모르는거 같습니다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

DB 설계 쉬운놈이 아니였습니다.
정복할때까지 공부 가즈아!!

profile
실력있는 개발자가 되보자!

1개의 댓글

comment-user-thumbnail
2022년 3월 31일

흑흑 파면팔수록 계속나오는 JPA, DBㅠㅠ 정복공부 가즈아,,,!!!

답글 달기