1. 들어가며
JPA 명세로 개발하는 SpringBoot에서는 Entity ID 생성 시 데이터베이스의 기본 키(primary key)를 자동 생성하는 방식을 사용합니다. 만약 주민번호나 SystemId처럼 비즈니스 로직 상 유일할 것처럼 보이는 자연키를 PK로 설정한다면, 추후 비즈니스 변경이나 유지보수 시 DB를 Migration하는 수준의 눈덩어리처럼 굴러올 수 있기 때문입니다.
JPA는 DB 기본 키 할당 전략으로 직접 할당 방식과 자동 생성 방식 두 가지를 제공합니다.
직접 할당 방식은 Application에서 기본 키를 직접 할당하는 방식이며, 자동 생성 방식은 대리 키를 사용하는 방식으로 AUTO, IDENTITY, SEQUENCE, TABLE 네 가지가 있습니다.해당 방식들은 사용하는 DB에 의존하는데, 대표적인 DB 가운데 MySQL은 IDENTITY를, Oracle은 SEQUENCE를 AUTO(default 전략)로 사용합니다.
2-1. DB 기본 키 할당 전략 (1) : 직접 할당 방식
직접 할당 방식은 em.persist()로 Entity를 영속성매니저에 저장하기 전에 DB가 아닌 Application 단에서 직접 기본 키를 할당해주어야 합니다.
@Entity
public class Book {
@Id
private Long id;
@NotNull
private String name;
}
Key Column에 @Id 어노테이션만 있어도 무방합니다.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
EntityManager em = emf.createEntityManager();
Book book1 = new Book();
book1.setName("노인과 바다");
book1.setId(1); // setter로 id를 할당하아지 않으면 error
em.persist(book1);
2-2. DB 기본 키 할당 전략 (2) : 자동 생성 방식
1) AUTO
- GenerationType.AUTO (기본 전략)
- 이 전략은 JPA가 데이터베이스에 따라 자동으로 선택하는 ID 생성 전략입니다. 데이터베이스에 따라 GenerationType.SEQUENCE, GenerationType.IDENTITY, GenerationType.TABLE 중 하나를 사용하게 됩니다.
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
2) IDENTITY
- GenerationType.IDENTITY
- 이 전략은 데이터베이스의 자동 증가(auto-increment) 기능을 사용하여 ID를 생성합니다. MySQL, PostgreSQL, SQL Server 등에서 사용할 수 있습니다.
@Entity
public class MyEntity {
@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을 지원하는 쓰기 지연 방식은 동작하지 않습니다.
3) SEQUENCE
- GenerationType.SEQUENCE
- 이 전략은 데이터베이스의 시퀀스(sequence) 기능을 사용하여 ID를 생성합니다. 시퀀스는 데이터베이스에서 고유한 값을 순차적으로 생성하는 객체입니다.
주로 Oracle, PostgreSQL 등에서 사용됩니다. 시퀀스를 사용하려면 @SequenceGenerator 어노테이션을 추가해야 합니다.
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_entity_seq")
@SequenceGenerator(name = "my_entity_seq", sequenceName = "my_entity_seq", allocationSize = 1)
private Long id;
}
4) TABLE
- GenerationType.TABLE
- 이 전략은 별도의 데이터베이스 테이블을 사용하여 ID를 생성합니다. 이 테이블은 모든 엔티티에 대한 ID를 관리하며, 여러 엔티티에서 공유할 수 있습니다. @TableGenerator 어노테이션을 추가해야 합니다.
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "my_entity_gen")
@TableGenerator(name = "my_entity_gen", table = "id_gen", pkColumnName = "gen_name", valueColumnName = "gen_val", allocationSize = 1)
private Long id;
}
댓글