@id, @GeneratedValue

XingXi·2023년 12월 28일
0

JPA

목록 보기
8/23
post-thumbnail

🍕 Reference

자바 ORM 표준 JPA 프로그래밍 : 교보문고
자바 ORM 표준 JPA 프로그래밍 - 기본편 : 인프런
블로그 참조!

이전에 Pesistence Context 내부에 1 차 Cache 에 대해서 공부했었다. 1차 Cache 에 Entity 를 저장하려면 @Id 값이 필요하다.
@Entity로 선언된 Entity 의 Id 를 할당하는 방법에 대해서 알아보자

@Id

Entity 의 Id 값임을 선언하는 Annotation 이며
Table 의 PK 와 객체의 필드를 매핑시켜주는 역할

Entity

package org.example.javamain.Entity;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Member2
{
    @Id
    private String str_id;

    private String name;

    public String getStr_id() {
        return str_id;
    }

    public void setStr_id(String str_id) {
        this.str_id = str_id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
@Entity
public class Member2
{
    @Id
    private String str_id;

main

            Member2 member2 = new Member2();
            member2.setStr_id("number1");
            member2.setName("a");
            em.persist(member2);

Id 값을 직접 입력할 수 있다.

DB에서는 PRIMARY KEY 값을 자동으로 할당해주는 기능을 사용한다.
이러한 기능들을 사용하기 위해서 JPA 에서는 @GeneratedValue 를 사용한다.


@GeneratedValue

영속성 관리 대상의 Entity 의 @Id 로 선언된 필드위에 위치하며
PK 값에 대한 생성 전략을 제공한다.
AUTO, IDENTITY, SEQUENCE, TABLE
strategy 속성값을 사용하며 기본값은 AUTO 이다.

@GeneratedValue

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface GeneratedValue {
    GenerationType strategy() default GenerationType.AUTO;
    String generator() default "";
}

GenerationType

public enum GenerationType {
    TABLE,
    SEQUENCE,
    IDENTITY,
    AUTO;
    private GenerationType() {
    }
}

GenerationType.Auto

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private String str_id;

Dialect 설정 값에 따라
나머지 전략들 중 자동으로 선택한다.
AUTO 사용 시 SEQUENCE, TABLE 전략으로 선택이 되는 것을 고려하여
SEQUENCE 혹은 KEY 생성 TABLE 을 미리 만들어야 할 수 있으니
사용하기전 확인이 필수다


GenerationType.IDENTITY

GenerationType.IDENTITY

MySql, PostgreSQL, SQL Server, DB2 에서 사용하며
PK 생성을 DB에 위임하는 전략이다.

GenerationType.IDENTITY 주의해야할 점

DB에서 PK 값 할당을 위임하는 방식이기 때문에 PK 를 DB 에 데이터가 INSERT 되어야 알 수 있다. Persistence Context에서 Entity 를 영속화 하려면 1차 캐시
Entity 가 저장이 되어야하고 이때 key 값이 @Id 로 선언된 필드 값이기 때문에
1차 캐시에 저장할 수 없고 영속화 시키지 못 한다.

그래서 Transaction이 커밋 되어야 DB 에 Query 를 보내는 것이 아닌 영속화 시킬 때 [EntityManager 의 persist()] Query 가 발생하고 그 결과를 1차 Cache 에 저장한다.
영속화 할때 Query 가 발생함으로 쓰기 지연은 IDENTITY 전략일 때 사용하지 못한다.

main

        try
        {
            Member2 member2 = new Member2();
            member2.setName("a");
            System.out.println(":::::: BEFORE PERSIST ::::::");
            em.persist(member2);
            System.out.println("member2.getId() : "+member2.getId());
            System.out.println(":::::: AFTER PERSIST ::::::");
        }

GenerationType.SEQUENCE

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

DB Sequence 를 사용하여 PK 를 할당하는 방식이다.
이때 Id의 데이터 타입은 는 Long 으로 사용하는 것을 권장한다
ORACLE, PostgreS!L, H2 등에서 사용할 수 있다.
참고로 DB Sequence 는 DB 에서 유일한 값을 순차적으로 생성하는 DB Object 이다.

Member2

@Entity
@SequenceGenerator(
        name = "TEST_SEQUENCE", 		// SequenceGenerator 이름 
        sequenceName = "MEMBER2_SEQ",	// Sequence 이름 
        initialValue = 1,				// Table 정의할 때 첫째 값 
        allocationSize = 1				// 한번 호출 시 증가하는 Sequence

)
public class Member2
{

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

@SequenceGenerator 를 사용하여 Sequence 를 생성하여 사용할 수 있다. Sequence 역시 DB 에서 관리하고 Entity 가 영속화 되기 이전에 sequence 값을 가져온다 ( persist 호출 시 )
sequence object 에서 sequence 를 들고 올 때 allocationSize 만큼 sequence 를 들고 오기 때문에 성능 최적화를 할 수 있다.

main

            Member2 member1 = new Member2();
            member1.setName("A");

            Member2 member2 = new Member2();
            member1.setName("B");

            Member2 member3 = new Member2();
            member1.setName("C");

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

            System.out.println("member1 : "+member1.getId());
            System.out.println("member2 : "+member2.getId());
            System.out.println("member3 : "+member3.getId());

            et.commit();

순서

  1. Table 정의와 함께 Sequence 가 정의 됨
  2. Entity 의 인스턴스가 생성될때 생성한 sequence 에서 allocationSize 만큼 sequence를 가져옴
  3. 1차 cache 에 entity 를 넣을 때마다 sequence 값을 순차적으로 할당함
    들고온 sequence 들은 memory 에서 관리

GenerationType.TABLE

PID 생성을 위한 Table 을 미리 생성하여 DB sequence 처럼 사용한다.
모든 DB 에 적용이 가능하다는 장점이 있지만
성능 저하 문제를 가지고 있다.

@Entity
@TableGenerator(
       name = "Table_SEQ_GEN",
       table = "SEQ_T",
       pkColumnValue = "MEMBER2_SEQ", allocationSize = 1
)
public class Member2
{
   @Id
   @GeneratedValue(
           strategy = GenerationType.TABLE,
           generator = "Table_SEQ_GEN"
   )
   private Long id;

0개의 댓글