JPA 하이버네이트 자동 키 생성 – 테이블 전략

요즘 스프링 부트로 프로젝트를 하면서 JPA 구현체인 하이버네이트를 함께 사용하고 있는데요,

이 과정에서 얻은 지식을 앞으로 쭉 블로그에 업데이트 할 계획입니다.
오늘은 키 생성 시, AUTO INCREMENT가 필요한 PK를 처리할 때 사용할 수 있는 JPA 표현에 대해 확인하겠습니다.

가장 만만한 “회원”정보를 갖는 엔터티를 다음과 같이 생성하겠습니다.

필드는 최대한 간소화 하여, USER_ID와 USER_NAME 두개만 가지고 있다고 하겠습니다.

그렇다면, 자바 코드로는 다음과 같이 정의할 수 있을 것입니다.

@Entity
@TableGenerator(name="SEQ_TB_USER", table="TB_SEQUENCES", pkColumnValue="USER_SEQ", allocationSize=1)
@Table(name="TB_USER")
public class User{
    @Id
    @GeneratedValue(strategy=GenerationType.TABLE, generator="SEQ_TB_USER")
    @Column(name="USER_ID")
    private Long id;
    
    @Column(name="USER_NAME")
    private String name;

    // getter, setter...
}

@TableGenerator 라는 애너테이션은 @GeneratedValue의 전략이 TABLE일때 사용할 수 있는 애너테이션입니다.

속성의 상관 관계는 다음과 같이 확인이 됩니다.

name=”SEQ_TB_USER” //자바 내에서 사용할 논리적인 시퀀스 이름, @GeneratedValue의 generator와 매핑
table=”TB_SEQUENCES” //테이블 전략에 필요한 데이터베이스 테이블 명
pkColumnValue=”USER_SEQ” //필드 중 어떤 필드값과 매팽시킬것인지 지정
allocationSize=1 //JPA에서 insert처리 시 마다 키값을 얼마나 증가시킬지 지정
위와 같은 속성은 다음과 같이 생긴 테이블에서 값을 참조하고, 증가처리시킵니다.

아래 DDL은 오라클 기준이며, 데이터 타입은 DBMS에 맞게 설정하세요.

CREATE TABLE TB_SEQUENCES(
    SEQUENCE_NAME VARCHAR2(255) NOT NULL,
    NEXT_VAL NUMBER(18, 0),
    PRIMARY KEY ( SEQUENCE_NAME )
)

필드명은 각각 SEQUENCE_NAME, NEXT_VAL 이어야 하고, NEXT_VAL의 기본값은 없어도 됩니다.

NEXT_VAL의 기본값이 없어도 JPA가 최초 INSERT 수행 시 알아서 해당 필드를 만들고 값을 1로 증가 시키기 때문입니다.

위 @TableGenerator 애너테이션에서 바라보는 테이블인 TB_SEQUENCES에 접근할 일이 생기는 경우,

즉 User 객체를 persist영역으로 올린 뒤 flush가 일어나면서 쿼리가 실행되는 그 순간에

최초인 경우 USER_SEQ라는 이름의 ROW가 INSERT되면서 최초의 NEXT_VAL은 allocationSize 만큼 부여될 것입니다.
즉, 최초의 INSERT 쿼리를 수행하게 되면 다음과 같은 모양을 갖게 될 것입니다.

SEQUENCE_NAME NEXT_VAL
USER_SEQ 1

JPA를 통해 INSERT쿼리가 생성되게 된다면,

위와 같은 TABLE전략을 가진 필드가 있는 경우 알아서 저장된 값을 1증가시킨 값으로 INSERT 처리한 뒤

그 값을 키로 사용하게 될 것입니다.
AUTO INCREMENT를 지원하는 DBMS를 사용하는 경우 그냥 전략을 AUTO로 놔도 문제없이 작동하겠지만,

오라클은 시퀀스를 별도로 생성해서 관리하도록 해 줘야하니, 이런 경우 에도 서로 호환되도록 테이블 전략을 사용하는것도 좋은 방법 중 하나인 것 같습니다.

(사실 아직 경험이 얼마 없다보니 어떤게 더 성능적으로 좋은지는 잘 모르겠네요 -_-;;)

You may also like...

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.