JAVA

[JAVA] JPA 기본키 매핑

응디 2021. 11. 11. 16:50

직접 할당 : @Id

자동생성 : @GeneratedValue


@GeneratedValue 의 종류

 

1. IDENTITY

  • 기본 키 생성은 데이터 베이스에 위임해줌
  • Mysql 의 auto_increment와 기능이 같다.
  • 주로 Mysql , postgreSQL, sql server, DB2에서 사용
identity는 null이 DB에 날라오면 그때 ID 값을 생성하여 DB에 삽입해준다.
제약이 생김 : DB에 넣을때 까지 키 값을 모르기 때문에 1차 캐시에 넣어줄 수가 없다.
따라서 identity만 예외적으로 commit 하기 전 persist 에서 DB에 쿼리를 날려준다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // int는 0이 있기 때문에 쓰기 애매하다.
Member member = new Member();
member.setUsername("JPA1");

System.out.println("=====================");
em.persist(member);
// 굳이 select를 안해도 바로 가져올수 있는 이유는? 
// insert하면 그 값을 return 해주는게 JDBC 드라이버에 들어있음
System.out.println("member.id : " + member.getId()); 
System.out.println("=====================");

코드 실행 결과 persist에서 insert 쿼리가 생성


2. SEQUENCE 

  • 데이터베이스 시퀀스 오브젝트 사용한다.
  • ORACLE 에서 많이 사용한다.
  • Sequence에서 값을 가져와서 사용한다.
sequence는 영속성 컨텍스트에 저장(persist) 하기위해서는 PK가 필요하기 때문에 
먼저 DB에 접속해 시퀀스 값을 받아와서 사용한다.
쿼리 날리는건 commit에서 실행!

※ 테이블 마다 시퀀스를 다르게 사용하고싶다면? 

@SequenceGenerator 사용 ( sequence에 이름을 붙여줘서 사용해야 함 )

@Entity
@SequenceGenerator(name="member_seq_generator", 
        sequenceName = "member_seq",    // 매핑할 데이터베이스 시퀀스 이름
        initialValue = 1,   		// 1부터 시작하고
        allocationSize = 50 )    	// 미리 50까지 시퀀스를 생성해두면 성능 최적화됨
public class Member {
    
    // pk 매핑
    // @GeneratedValue(strategy = GenerationType.IDENTITY) : mysql auto_increment랑 같음

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_seq_generator")
    private Long id; // int는 0이 있기 때문에 쓰기 애매하다.

    // DB 컬럼명은 name을 하고싶고 객체 이름은 다른 걸 하고싶을때
    @Column(name = "name")
    private String username;


    // 기본생성자
    public Member(){
        
    }

}

지정해준 seq 이름으로 호출 예시
seq DB 생성 예시


3. TABLE

  • 키 생성용 테이블 사용한다. ( 테이블 하나 생성하여 거기서 뽑아서 사용함 )
  • 장점 : 모든 DB에서 사용 가능하다 ( 테이블을 만들어서 사용하니까 )
  • 단점 : 테이블을 만들어서 뽑아서 쓰니까 성능 문제가 있음
  • @TableGenerator 필요
  • 성능 문제 때문에 실 운영에서는 잘 사용하지 않음
package hellojpa;

import javax.persistence.*;
import java.util.Date;

@Entity
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        table = "MY_SEQUENCES", // 생성할 테이블 이름
        pkColumnValue = "MEMBER_SEQ",    // pk 이름
        allocationSize = 1)
public class Member {
    
    // pk 매핑
    // @GeneratedValue(strategy = GenerationType.IDENTITY) : mysql auto_increment랑 같음

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id; // int는 0이 있기 때문에 쓰기 애매하다.

    // DB 컬럼명은 name을 하고싶고 객체 이름은 다른 걸 하고싶을때
    @Column(name = "name")
    private String username;


    // 기본생성자
    public Member(){
        
    }

}

DB 테이블 생성 예시

 


4. AUTO

  • 방언(DB)에 따라 자동 지정됨 
  • 기본 지정 값

권장하는 식별자 전략

  • 기본 키 제약 조건 : null 아님, 유일, 변하면 안된다.
  • 미래까지 이 조건을 만족하는 자연키(주민등록번호, 전화번호)는 찾기 어렵다.
  • 대리키(대체키)를 사용하자. → 비즈니스와 전혀 상관없는 걸 사용
  • 주민등록번호도 기본 키로 적절치 않음 → 여기저기 외래키로 쓰이기엔 개인정보기 때문에
  • 권장 : Long형 + 대체키 + 키 생성전략 내용(auto_increment, seq, uuid ...등 쓰는걸 권장 )