ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JPA] 기본키(PK) 매핑 전략 IDENTITY, SEQUENCE, TABLE, AUTO
    JPA 2023. 5. 20. 16:28

    [JPA] 기본키(PK) 매핑 전략 

    GenerationType.IDENTITY

    GenerationType.SEQUENCE

    GenerationType.TABLE

    GenerationType.AUTO


    안녕하세요? 장장스입니다.

    오늘은 기본키(PK) 매핑 전략에 대해 정리해보겠습니다.

     

     

    기본키 맵핑 어노테이션


    @Id

    기본키를 사용자가 직접 할당하여 사용한다.

    @Id
    private String id;

     

    @GeneratedValue

    기본키를 자동생성할때 사용한다.

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

    기본키를 자동생성하는 @GeneratedValue 어노테이션은 4가지 전략이 있다.

     

     

    @GeneratedValue (strategy = GenerationType.IDENTITY)


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private String id;

    IDENTITY는 데이터베이스에 위임하는 전략이다. MySQL의 AUTO_INCREMENT와 같은 기능을 제공하는 MySQL, PostgreSQL, SQL Server, DB2에서 사용할 수 있다.

     

    IDENTITY 전략은 DB 적재 되기 전까지 PK 값을   없다. 예를 들어, AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID값을 알 수 있다.

    JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL을 실행한다. JPA에서는 PK값이 없는 데이터는 영속성 컨텍스트에 올릴 수가 없다. 때문에, persist 메서드가 실행될때 바로 insert가 실행되고 key 값을 가져온다. JDBC 내부적으로 insert 시에 key값을 가져오게 되어 있어 약간의 리소스를 더 사용하게 된다는 단점이 존재한다.

    위와 같은 단점은, 개발할 때 크게 문제가 되지는 않는다.

     

    @GeneratedValue (strategy = GenerationType.SEQUENCE)


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

    SEQUENCE는 데이터베이스 시퀀스 오브젝트를 사용한다. 보통 ORACLE의 기본키 생성 전략으로 많이 사용한다.

    시퀀스를 지정하지 않으면 기본 시퀀스 이름으로(ex.. hibernate_seq) 시퀀스 오브젝트를 생성하며, 직접 시퀀스 오브젝트를 설정하기 위해 @SequenceGenerator 어노테이션과 함께 사용한다.

    @SequenceGenerator(
            name = "ZZS_SEQ_GENERATOR",
            sequenceName = "ZZS_SEQ", //매핑할 데이터베이스 시퀀스 이름
            initialValue = 1, allocationSize = 50)
    public Class Zangzangs{
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ZZS_SEQ_GENERATOR")
        private Long id;
        
        ...
        ...
        
    }

     

    SEQUENCE 전략을 생성할 때, int, long와 같은 원시타입(primitive type)은 0이 있어 사용을 추천하지 않는다.(기본키가 0부터 시작이 된다.)

    보통 Integer, Long와 같은 래퍼 클래스를(wrapper class) 사용하며, Integer의 최대 크기가 21억밖에 안된다. 통장에 21억만 있으면 좋겠네.. (MAU가 높은 규모의 회사이거나, 장기간 서비스가 이루어지면 21억은 금방 찰수도 있다.)

    요즘은 컴퓨터 성능이 좋아진 이유로 가능하면 무조건 Long 사용을 추천한다.

     

    @SequenceGenerator

    속성 설명 기본값
    name 식별자 생성 이름 필수
    sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름 hibernate_sequence
    initialValue DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정한다. 1
    allocationSize 시퀀스 한번 호출에 증가하는 수
    성능최적화에 사용되며 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다.
    50
    catalog 데이터베이스 catalog  
    schema 데이터베이스 schema  

     

    @GeneratedValue (strategy = GenerationType.TABLE)


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

    TABLE은 키 생성용 테이블을 사용한다. 시퀀스 전략을 흉내내는 전략으로 모든 DB에서 사용이 가능하다는 장점이 있다.

    SEQUENCE 전략처럼 @TableGenerator 어노테이션이 필요하다. 

    @TableGenerator(
            name= "ZZS_SEQ_GENERATOR",
            table = "MY_SEQUENCES",
            pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
    public class Zangzangs{
       @Id
       @GeneratedValue(strategy = GenerationType.TABLE , generator = "ZZS_SEQ_GENERATOR")
       private Long id;
       
       ...
       ...
    }

    다만, 시퀀스를 값 조회보다 테이블 조회하는 성능상의 단점이 커서 일반적으로 사용하지 않는다.

     

    @TableGenerator

    속성 설명 기본값
    name 식별자 생성 이름 필수
    table 키생성 테이블명 hibernate_sequences
    pkColumnName 시퀀스 칼럼명 sequence_name
    pkColmnValue 키로 사용할 값 이름 엔티티 이름
    valueColmnName 시퀀스 값 칼럼명 next_val
    initialValue 초기 값, 마지막으로 생성된 값이 기준이다. 0
    allocationSize 시퀀스 한 번에 호출에 증가하는 수
    성능 최적화에 사용됨
    50
    catalog 데이터베이스 catalog  
    schema 데이터베이스 schema  
    uniqueConstraints 유니크 제약 조건을 지정한다.  

     

    @GeneratedValue (strategy = GenerationType.AUTO)


    AUTO는 데이터베이스 방언에 따라 자동 지정되며, strategy 속성의 디폴트 값이다.

    데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략이 선택이 된다. 예를들어 오라클을 사용할 경우 SEQUENCE 전략이 선택된다.

    JPA 버전마다 AUTO 전략이 달라질 수 있으므로 확인 후에 사용해야 한다.

     

     

     

    Post


    References


     

     


    잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)

     

     

    댓글