이번 포스팅에서는 JPA에서 식별자를 생성하는 방식에 대하여 알아보도록 하겠습니다. 식별자 생성 방식에는 애플리케이션에서 직접 생성하는 방식(특별한 식별자 규칙이 있는 경우)과 JPA 에서 생성하는 방식이 있습니다. JPA가 식별자를 생성하는 방식은 다시 식별 칼럼 방식, 시퀀스 방식, 테이블 방식이 있습니다.


JPA에서 식별자를 생성하는 방식


식별 칼럼 방식

JPA가 식별 칼럼을 이용해서 식별자를 생성하려면 @Id 애노테이션 대상에 추가적인 설정이 필요합니다. @GeneratedValue 애노테이션을 추가하고 strategy 값을 설정하면 됩니다.

@Entity @Table(name="hotel_review") public class Review { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; }


GenerationType.IENDTITY 는 식별자 생성을 데이터베이스의 식별자 생성 방식을 사용하여 식별자를 생성하는 방법입니다. 데이터베이스에서 기본키(식별자)를 auto_increment로 생성한다면 이에 의존하여 엔티티의 식별자를 생성하는 것이죠. 


사실 데이터베이스의 식별 칼럼이라는 것을 잘 모르겠어서 아래에서 정리할 "시퀀스 방식"과 큰 차이점을 모르겠네요.. 글을 읽으신 선배님이 계시다면 가르침 부탁드립니다 ㅠㅠ 


시퀀스[각주:1] 방식

@SequenceGenerator 애노테이션을 이용하면 데이터베이스의 시퀀스를 이용하여 식별자를 생성할 수 있습니다. 

    @Id
    @SequenceGenerator(
        name = "review_seq_gen",
        sequenceName = "hotel_review_seq",
        allocationSize = 1
    )
    @GeneratedValue(generator="review_seq_gen")
    private Long id;



@SequenceGenerator의 name으로 설정한 값은 @GeneratorValue 애노테이션에서 generator로 사용됩니다. sequenceName으로 설정한 값은 실제 데이터베이스의 시퀀스이며, allocationSize는 시퀀스 증가값을 설정합니다. 참고로 allocationSize의 기본값은 50인데 1로 사용해야 별탈없이 사용이 가능한데 다음에 기회가 된다면 정리하도록 하겠습니다.


시퀀스 방식을 사용하는 경우는 persist() 시점에 insert 쿼리를 실행하지 않고 시퀀스 관련 쿼리만 실행하여 식별자를 생성합니다.


1
2
3
transaction.begin();
Review review = new Review("KR-S-01"5"최고입니다", new Date());
entityManager.persist(review); // select hotel_review_seq.nextval from dual 
cs



테이블 방식

식별자를 구분하기 위해 사용할 주요키 칼럼과 다음 식별자로 사용할 숫자를 보관할 컬럼을 가지는 테이블을 이용하는 방법입니다. 아래의 id_gen 테이블은 entity 컬럼에서 엔티티를 구분하기위한 용도로 사용되고 nextid 컬럼은 해당 엔티티의 다음 식별자로 사용된다.


1
2
3
4
create table id_gen(
    entity varchar(100not null primary key,
    nextid int
engine innodb character set utf8;
cs


그럼 테이블 방식으로 엔티티의 식별자를 생성해보도록 하겠습니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
public class City {
    @Id
    @TableGenerator(name = "idgen",
        table = "id_gen",
        pkColumnName = "entity",
        pkColumnValue = "city",
        valueColumnName = "nextid",
        initialValue = 0,
        allocationSize = 1)
    @GeneratedValue(generator = "idgen")
    private Long id;
}
cs


  • name : 테이블 생성기의 이름을 지정합니다. @GeneratedValue의 generator 속성값으로 사용됩니다.
  • table: 식별자를 생성할 때 사용할 테이블을 지정합니다.
  • pkColumnName: 식별자 생성용 테이블의 주요키 칼럼을 지정합니다.
  • pkColumnValue: 주요키 칼럼에 사용할 값을 지정합니다. 각 @TableGenerator마다 다른 값을 사용해야하며 보통 엔티티 클래스의 이름을 사용합니다.
  • valueColumnName: 생성할 식별자를 갖는 칼럼을 지정합니다.
  • initialValue: 식별자의 초기값을 지정합니다. 
  • allocationSize: 식별자를 해당값만큼 증가시킵니다. 이 값 역시 1로 설정해야 합니다.


1
2
3
4
5
6
7
8
9
10
11
transaction.begin();
 
City city = new City("서울");
entityManager.persist(city);
 
transaction.commit();
 
 
//select tbl.nextid from id_gen tbl where tbl.entity='city' for update
//insert into id_gen (entity, nextid) values ('city', 1) // 레코드가 존재하지 않을 때 식별자 테이블에 insert, 이미 식별자가 존재하는 경우는 쿼리 
//update id_gen set nextid=2 where nextid=1 and entity='city'
cs



위의 코드는 persist() 메서드를 실행하는 시점에 식별자 테이블에서 식별자를 구하고 다음에 식별자로 사용할 값을 업데이트하는 것을 확인할 수 있습니다.

  1. 순차적으로 증가하여 유일한 값을 생성해주는 객체 [본문으로]

'웹 개발 > JPA 프로그래밍' 카테고리의 다른 글

EntityManager 와 영속 컨텍스트  (0) 2019.03.03
@Embeddable  (0) 2019.02.19
엔티티(Entity)와 엔티티매니저(EntityManager)  (0) 2019.01.01
JPA란  (0) 2018.12.29

+ Recent posts