인프런 김영한 강의 정리/자바 ORM 표준 JPA 프로그래밍 기본편

JPA 기본 | 기본키 매핑 | @id, @GeneratedValue

백엔드 개발자 - 젤리곰 2024. 6. 10. 21:27
728x90

1. 직접 할당

@Id만 사용한다.

 

✅예시

@Id
private String id;

 

2. 자동 생성

@GeneratedValue 애노테이션과 strategy 속성으로 GenerationType을 세팅해야한다.

타입 종류 설명
IDENTITY 기본키를 자동으로 증가시킨다. 
SEQUENCE DB 시퀀스를 사용하여 기본키를 생성한다.
@SequenceGenerator를 사용하여 시퀀스를 정의해야한다.
ex) Oracle, PostgreSQL, DB2, H2, MariaDB, SQL Server 사용가능
TABLE 별도의 키 생성용 테이블을 사용하여 기본키 값을 생성한다. 
@TableGenerator를 사용하여 테이블을 정의해야한다.
모든 DB에 적용이 가능하다.
AUTO 방언(DB 문법)에 따라 자동 지정, 기본값이다.

✔️ IDENTITY

- IDENTITY는 기본키 생성을 데이터베이스에 위임한다.

ex) MySQL, PostgreSQL, SQL Server, DB2에서 사용

 

- 예외적으로 em.persist() 시점에 즉시 INSERT SQL을 실행한다.

(commit시점에 insert 쿼리가 실행되지 않는다는 점!

그래서 한번에 모아서 insert를 할 수가 없다.)

 

- SEQUENCE를 지원하지 않는 DB에서는 SEQUENCE 타입을 쓸 수 없다.

이런 경우, IDENTITY를 사용한다.

 

✔️ SEQUENCE

- 시퀀스 오브젝트를 만든다.

- id 타입은 Long을 써야한다.

 

✔️TABLE

- 시퀀스를 지원하지 않는 DB에서 시퀀스와 비슷한 방식으로 기본 키를 생성할 수 있도록 한다.

- 단, 시퀀스보다 성능이 떨어진다.

 

 

1) @SequenceGenerator 사용법

 

  • name: 시퀀스 생성기의 이름. @GeneratedValue 애노테이션의 generator 속성에서 참조한다.
  • sequenceName: 실제 데이터베이스 시퀀스 이름.
  • initialValue: 시퀀스의 초기 값.
  • allocationSize: 시퀀스가 증가하는 단위. (기본값 50) (성능최적화에 사용된다.)

✅예시

package hellojpa;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;


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

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

    @Column(name = "name", nullable = false)
    private String username;

    public Member() {
    }

}

 

 

✅애플리케이션 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member member1 = new Member();
            Member member2 = new Member();
            Member member3 = new Member();
            member1.setUsername("A");
            member2.setUsername("B");
            member3.setUsername("C");

            em.persist(member1);
            em.persist(member2);
            em.persist(member3);

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }

    }
}

 

✅로그

Hibernate: 
    create sequence MEMBER_SEQ start with 1 increment by 1
Hibernate: 
    create table Member (
        id bigint not null,
        name varchar(255) not null,
        primary key (id)
    )
    
Hibernate: 
    select
        next value for MEMBER_SEQ
Hibernate: 
    /* insert for
        hellojpa.Member */insert 
    into
        Member (name, id) 
    values
        (?, ?)

 

✔️IDENTITY와 다르게 commit 시점에서 insert 쿼리에 실행된다.

(모아서 insert하는게 가능하다.)

 

✅실행 결과 확인

시퀀스 오브젝트가 생성됐다. 

 

애플리케이션 실행부에서 id값을 세팅하지 않아도 ID컬럼을 기본키로 하여 순차적으로 세팅된다.

2) @TableGenerator 사용법

 

  • name: 생성기 이름. @GeneratedValue 애노테이션의 generator 속성에서 참조한다.
  • table: 키 값을 저장할 테이블 이름.
  • pkColumnName: 시퀀스 이름을 저장할 컬럼 이름.
  • valueColumnName: 다음 키 값을 저장할 컬럼 이름.
  • pkColumnValue: 이 생성기에서 사용할 시퀀스 이름.
  • initialValue: 초기 값.
  • allocationSize: 증가 값. (기본값 50, 성능 최적화에 사용된다.)

✅예시 

package hellojpa;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;


@Entity
@Getter
@Setter
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR", //generator 속성 참조
        table = "MY_SEQUENCES", //키 값 저장할 테이블명
        pkColumnValue = "MEMBER_SEQ", allocationSize = 1) //시퀀스 이름을 저장할 컬럼명
public class Member {

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

    @Column(name = "name", nullable = false)
    private String username;

    public Member() {
    }

}

 

 

✅애플리케이션 실행부

package hellojpa;

import jakarta.persistence.*;

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Member member1 = new Member();
            member1.setUsername("C");

            em.persist(member1);

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }

    }
}

 

✅로그

Hibernate: 
    drop table if exists Member cascade 
Hibernate: 
    drop table if exists MY_SEQUENCES cascade 
Hibernate: 
    create table Member (
        id bigint not null,
        name varchar(255) not null,
        primary key (id)
    )
Hibernate: 
    create table MY_SEQUENCES (
        next_val bigint,
        sequence_name varchar(255) not null,
        primary key (sequence_name)
    )
    
Hibernate: 
    insert into MY_SEQUENCES(sequence_name, next_val) values ('MEMBER_SEQ',0)
Hibernate: 
    select
        tbl.next_val 
    from
        MY_SEQUENCES tbl 
    where
        tbl.sequence_name=? for update
Hibernate: 
    update
        MY_SEQUENCES 
    set
        next_val=?  
    where
        next_val=? 
        and sequence_name=?
Hibernate: 
    /* insert for
        hellojpa.Member */insert 
    into
        Member (name, id) 
    values
        (?, ?)

시퀀스 테이블이 만들어지고 INSERT 쿼리가 실행된다.

 

✅실행 결과 확인

시퀀스 테이블이 생성됐다.

애플리케이션 실행부에서 id값을 따로 세팅해주지 않아도 ID값이 1로 저장됐다.

 

 

728x90