본문 바로가기

내일배움캠프/Today I Learned

[TIL] 나의 서른 여덟번째 회고록

Today Error


 

 

 

게시글 작성하고 DB를 확인해보았더니

DB에 저장되는 id값이 1이 아닌 2부터 count 되는 것을 알았다. 

음.? 왜그러지? Post.java(Entity)를 확인 해보니

Post의 id값을 GenerationType.Auto로 설정한 것..! 

IDENTITY랑 Auto랑은 무슨 차이가 있는거지? 싶어서 찾아봤다.

 

GenerationType.Auto

GenerationType.Auto는 SEQUENCE 전략으로

굳이 INSERT 쿼리가 DB에 나가지 않아도 id 값을 알 수 있으므로

AUTO 일 땐 INSERT 쿼리가 나가지 않음.

 

GenerationType.IDENTITY 

엔티티를 영속화할 때 id 값을 알아야 하므로

즉시 INSERT 쿼리가 발생 됨.

 

시퀀스 전략과 IDENTITY 전략???

솔직히 말하면

JPA을 접하게 되면서 이렇게까지 상세하게 개념을 알려고 해보지 않았던 것 같다. 

아~ 그냥 그렇구나 정도에서 그쳤었는데

역시 개발은 의미없는 코드가 없다는 것을 

또 한번 깨닫고

 

 JPA 기본키 생성 전략을 좀 더 자세하게 알아보고자

아래 1일 1개념에 정리를 해본다.

 

1일 1개념


★ JPA 기본 키 생성 전략 ★

(IDENTITY, SEQUENCE, TABLE)

 

JPA가 제공하는 DB 기본 키 할당 전략 

1. 직접 할당 방식, 2. 자동 생성 방식 두 가지

 

1. 직접 할당 방식

Application에서 기본 키를 직접 할당하는 방식

 

2. 자동 생성 방식

대리 키를 사용하는 방식으로

 IDENTITY, SEQUENCE, TABLE 세가지가 있다.

 

※ 해당 방식들은 사용하는 DB에 의존하며
MySQL은 IDENTITY 사용, Oracle은 SEQUENCE 사용을 한다.

 


직접 할당 방식

 

직접 할당 방식을 사용할 경우 Entity를 생성할 때 Key Column에 @Id만 사용해 주어도 된다.

@Id
private long id;

 

@Id가 적용 가능한 Java Type은 아래와 같다.

 

  • Java 기본형(int, double, long ...)
  • Java Wrapper 형
  • String
  • java.util.Date
  • java.sql.Date
  • java.math.BigDecimal
  • java.math.BigInteger

 

해당 전략 em.persist()로 Entity를 저장 하기 전, Application에서 직접 기본 키를 할당해주어야 한다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");

EntityManager em = emf.createEntityManager();

User user = new User();
user.setName("gillog");
user.setId(1);

em.persist(user);

 

 


자동 생성 방식

 

자동 생성 방식을 사용할 경우 @Id와 @GeneratedValue를 사용한다.

IDENTITY

★ 기본 키 생성을 DB에 위임하는 전략이다.

MySQL과 같이 Sequence를 제공하지 않고, AutoIncrement 기능을 제공해,

기본 키 값을 자동으로 생성하는 DBMS에서 사용한다.

주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다.

아래와 같이 사용할 수있다.

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

IDENTITY전략은 Data를 DB에 Insert한 후 기본 키 값을 조회할 수 있다.

 

Entity에 식별자 값을 할당하려면 JPA는 추가로 DB를 조회해야 하는데,

Hibernate는 JDBC3에 추가된 Statement.getGeneratedKeys()를 사용 DB와 한번만 통신한다.
해당 메소드는 Data를 저장하면서, 생성된 기본 키 값을 가져온다.

 

하지만 Entity가 영속 상태가 되려면 식별자가 반드시 필요한데,

DB에 저장해야만 식별자를 구할 수 있는 방식이므로,

em.persist()호출 즉시 Insert Query를 DB에 전달해 식별자를 가져오므로,

Transaction을 지원하는 쓰기 지연 방식이 동작하지 않는다.


SEQUENCE

해당 방식 DB Sequence를 사용해 기본 키를 할당하는 방식으로,

Sequence 전략을 지원하는 Oracle, PostgreSQL, DB2, H2 DB에서 주로 사용한다.

아래와 같이 DB에서 Seqeunce를 생성 후에 사용할 수 있다.

CREATE SEQUENCE USER_SEQ START WITH 1 INCREMENT BY 1;

 

후에 Entity를 생성할 때 @SequenceGenerator Annotation을 사용한다.

@Entity
@SequenceGenerator(
	name = "USER_SEQ_GENERATOR"
    , sequenceName = "USER_SEQ"
    , initialValue = 1
    , allocationSize = 1
)
public class User {

    @Id
    @GeneratedValue(
    	strategy = GenerationType.SEQUENCE
    	, generator = "USER_SEQ_GENERATOR"
    )
    private long id;
    
}

 

@SequenceGenerator Annotation에서 사용 가능한 속성들은 아래와 같다.

name 식별자 생성기 이름 없음 지정 필수.
sequenceName DB에 등록되어 있는 Sequence이름 hibernate_sequence
initalValue(DDL) DDL 생성시에만 사용, Sequence DDL 생성시 처음 시작 value를 설정 1
allocationSize Sequence 한번 호출시 증가하는 수(성능 최적화에 사용) 50
catalog, schema DB catalog, schema 이름

 ★ IDENTITY  VS  SEQUENCE  

IDENTITY 전략 먼저 Entity를 DB에 저장한 후에,

식별자를 조회해 Entity의 식별자로 할당하는 전략이다.

 

SEQUENCE 전략 em.persist() 호출 전에 먼저 DB Sequence를 먼저 조회한다.

그 후 조회한 식별자를 Entity에 할당한 후 Entity를 영속상태로 저장한다.

그 후 Transaction을 Commit하여 Flush가 발생할 때 해당 Entity를 DB에 저장한다.

 

 

< 마무리 >

(1) IDENTITY전략은 값을 DB할당 -> DB에서 식별자 조회 -> 마지막에 Entity식별자로 할당  

 

(2) SEQUENCE 전략 -> DB Sequence 조회 -> Entity 식별자 할당

-> Entity를 영속상태로 저장 -> Transaction 발생 시 해당 식별자를 DB에 저장

 

 

출처 : https://velog.io/@gillog/JPA-%EA%B8%B0%EB%B3%B8-%ED%82%A4-%EC%83%9D%EC%84%B1-%EC%A0%84%EB%9E%B5IDENTITY-SEQUENCE-TABLE

 

[JPA] 기본 키 생성 전략(IDENTITY, SEQUENCE, TABLE)

자바 ORM 표준 JPA 프로그래밍JPA가 제공하는 DB 기본 키 할당 전략은 직접 할당 방식, 자동 생성 방식 두 가지이다.이 중 직접 할당 방식은 Application에서 기본 키를 직접 할당하는 방식이다.자동 생

velog.io