[JPA] @Id,  @GeneratedValue

Kyeong Ju·2024년 4월 24일

@Id

@Id 파일의 주석으로 적혀있는 내용을 번역해 정리하자면 아래와 같다.

entity의 PK를 지정한다. @Id 어노테이션이 적용될 field나 property는 아래의 타입 중 하나에 속해야 한다.

any Java primitive type; 
any primitive wrapper type; 
String; java.util.Date; java.sql.Date; java.math.BigDecimal; 
java.math.BigInteger;

entity의 PK로 매핑된 column은 primary table의 PK로 간주한다. 만약 @Column 어노테이션이 지정되어있지 않으면, PK column의 이름은 PK property나 field의 이름으로 간주된다.

이를 정리하자면, @Id 어노테이션을 통해 entity의 property나 field를 table의 기본키(PK)에 매핑시켜준다는 걸 알 수 있다. @Id 어노테이션을 사용한다고 id의 값이 생성되는 건 아니기 때문에 직접 할당을 해주거나 후술할 @GeneratedValue 를 이용해 값을 넣어줘야 한다.




@GeneratedValue

@GeneratedValue 파일의 주석으로 적혀있는 내용을 번역한 내용은 아래와 같다.

PK의 값을 생성하는 전략에 대한 명세를 제공한다. @GeneratedValue는 PK property나 field에 적용 되거나, @Id와 함께 매핑된 슈퍼클래스에서 사용될 수 있다. @GeneratedValue는 simple PK를 돕기 위해 요구되어 사용될 뿐, derived PK를 위해서는 사용되지 않는다.

@GeneratedValue 는 말 그대로 key에 들어갈 값을 생성하는 전략을 위한 어노테이션인데, strategy 속성을 통해 지정할 수 있다. jakarta persistence에 관한 문서에서 자세한 내용을 파악할 수 있다.


AUTO

하이버네이트(hibernate)에게 전략 선택을 위임하는 옵션이다. 이 경우 사용하는 DB에 따라 하이버네이트가 전략을 선택하기 때문에 각 DB별로 다른 전략이 선택될 수 있다. AUTO의 장점이라면 DB 종류가 변경돼도 전략을 수정하지 않아도 된다는 점에 있지만, 하이버네이트가 선택한 전략에 따라 선행되어야할 부분이 있음을 유의해야한다.


IDENTITY

IDENTITY 전략은 기본키 생성에 대한 전략을 DB에 위임한다. 예를 들어 MySQL, PostgreSQL이 auto-increment로 기본키를 자동으로 생성하는 DB에서 사용한다.
IDENTITY 전략 순서상 먼저 Entity를 DB에 저장하고, 그 후에 키를 조회해 Entity에 할당한다.


SEQUENCE

DB의 SEQUENCE 객체를 이용해 기본키를 생성하는 방식이다. 따라서 SEQUENCE 객체가 있는 DB(ORACLE, PostgreSQL)의 경우 사용할 수 있는 전략이다. SEQUENCE 객체를 통해 기본키를 생성하는 경우, 순차적으로 증가하는 순번을 반환하여 unique한 값의 기본키가 보장이 된다.

만약 사용하는 DB에 sequence 객체가 없다면, @SequenceGenerator 를 통해 사용이 가능하다. (@SequenceGenerator가 sequence를 관리할 객체를 생성하기 때문이다.) 단, 이 경우 JPA ddl-auto 설정이 되어있어야 한다.

SEQUENCE 전략은 DB에서 sequence를 먼저 조회한 후, 조회된 식별자를 Entity에 할당하고 em.persist()를 호출해 etity를 저장한다. 이 점에 있어 IDENTITY와의 차이가 있따.

  • DDL (Data Definition Language)
  • ddl-auto의 create 옵션을 사용하면 drop+create가 일어나고 create-drop은 create 옵션처럼 기존 테이블이 있으면 drop하고 create한다.(drop은 종료 시점에 일어난다.) create, create-drop, update 옵션은 db에 큰 영향을 주기 때문에 운영 단계에서는 사용하면 안된다.

TABLE

TABLE 전략의 경우 기본키 할당을 위해 키 할당 시점 이전에 테이블이 우선적으로 생성돼야 한다. 생성한 TABLE을 @TableGenerator 어노테이션을 통해 entity와 매핑하고, 내부적으로 SEQUENCE 전략을 유사하게 구현되는 방식이다.


UUID

UUID(Universally Unique Identifier) 즉, 절대 겹치지 않는 유일성을 보장하는 방법이다.

@GeneratedValue(strategy = GenerationType.UUID)
private UUID id; // UUID -> java.util

UUID 전략을 사용하면 간단하게

Here, we should note that when we set a column to have type java.util.UUID, Hibernate tries to map it to the corresponding UUID type in the database. This type can differ from one database to another.

So, the exact type practically depends on the Hibernate dialect set. For instance, if we’re using PostgreSQL, then the corresponding type will be UUID in PostgreSQL. If we’re using Microsoft SQL Server, then the corresponding type will be UNIQUEIDENTIFIER. However, if we use String as the Java ID type, then Hibernate maps it into some SQL textual type, such as TEXT or VARCHAR. (from baeldung)


UUID와 IDENTITY 생각해볼 점

  • 순서, 길이
    IDENTITY 전략을 통해 1씩 auto-increment되는 식별자를 기본키로 사용하게 되면 장점은 쉽다는 거고 단점 또한 쉽다는 거다. 순차적으로 데이터의 PK가 생성되기 때문에 다른 데이터의 id를 유추할 수 있다는 점이 문제가 된다. 통한 반면 UUID는 기본키를 통한 순서를 보장하지 않는다. 직관적이지 않고 메모리를 많이 차지한다는 점(16byte)이 단점이다. (long 자료형은 8byte)

    벨로그의 경우 UUID
    https://velog.io/write?id=5a82e8f0-467c-****-****-362aae3c6411```
  • 분산 환경
    서비스가 분산 DB 환경이라고 가정하였을 때, auto-increment의 예상되는 문제점이 있다. 각각의 DB에서 식별자로 사용하려는 값이 unique한가 확인을 해야한다는 점이다. 그렇지 않으면 충돌이 일어날 수 있다. 물론 이를 해결하는 방법들도 있기는 하다.(분산 시스템의 설계적인 해결이나 매번 확인한다거나...)


그외 이슈들

- AUTO 전략을 피하는 이유




결론

  1. 나는 학습용 프로젝트를 진행하고 있다.
    • 개발자의 입장에서 직관적인 것을 추구해도 괜찮다.
    • 보안상의 문제를 고민할 이유가 크게 없다.
  2. 단일 DB시스템이다.

따라서, IDENTITY 전략을 사용할 것이다.




참고
https://devcamus.tistory.com/16
https://velog.io/@gillog/JPA-기본-키-생성-전략IDENTITY-SEQUENCE-TABLE
https://www.baeldung.com/java-hibernate-uuid-primary-key
https://ssdragon.tistory.com/162

profile
백엔드 학습 공간

0개의 댓글