식별자 전략
2023. 2. 28. 09:06ㆍJPA
◎ 기본키 매핑
-> jpa에서 @Id 애너테이션이 붙은 필드가 기본키 컬럼이 된다.
-> jpa에서는 이 기본키를 어떤 방식으로 생성할지에 대해 다양한 전략을 제공한다.
-> 기본키 생성 전략은 애플리케이션 코드에서 기본키를 직접 할당하는 기본키 직접 할당과 자동으로 생성하는 기본키 자동 생성이 있다.
-> 기본 키 자동 생성(IDENTITY, SEQUENCE, TABLE)
- IDENTITY : 기본키 생성을 데이터베이스에 위임하는 방식. 데이터베이스가 MySQL 이라면 AUTO_INCREMENT 기능으로 자동 증가 숫자를 기본키로 사용한다.
- SEQUENCE : 데이터베이스에서 제공하는 시퀀스를 사용하여 기본키를 생성한다.
- TABLE : 별도의 키 생성 테이블을 사용한다.
◎ IDENTITY와 SEQUENCE의 차이
<IDENTITY>
-> 테이블에 데이터를 insert하면 식별자를 얻을 수 있다.
-> 영속성 컨텍스트에 엔티티를 저장하려면 테이블에 insert를 먼저 처리해야 하기 때문에 commit()을 명시적으로 호출하지 않아도 persist()호출 만으로도 commit이 발생한다.
-> 예시
@Entity // 해당 클래스는 엔티티 클래스다. -> jpa 관리 대상 엔티티가 된다.
public class Member {
@Id //
@GeneratedValue(strategy = GenerationType.IDENTITY) // 식별자 생성 전략
private long memberId;
private String email;
private String name;
private String phone;
}
@Configuration
public class JpaIdDirectMappingConfig {
private EntityManager em;
private EntityTransaction tx;
@Bean
public CommandLineRunner testJpaSingleMappingRunner(EntityManagerFactory emFactory) {
this.em = emFactory.createEntityManager();
this.tx = em.getTransaction();
return args -> {
tx.begin();
em.persist(new Member()); // Member 엔티티에 IDENTITY 전략이 적용되어 여기에서 기본키 값은 할당하지 않는다.
tx.commit();
Member member = em.find(Member.class, 1L);
System.out.println("# memberId : " + member.getMemberId());
};
}
}
-> 결과
Hibernate: drop table if exists member CASCADE
Hibernate: create table member (member_id bigint generated by default as identity, email varchar(255), name varchar(255)
...
Hibernate: insert into member (member_id, email, name, phone) values (default, ?, ?, ?)
# memberId : 1
<SEQUENCE>
-> 테이블에 데이터를 insert하기 전에 SEQUNECE로부터 식별자를 미리 얻을 수 있다.
-> 따라서 persist() 호출 시 영속성 컨텍스트에 엔티티가 저장되고, commit()을 호출하기 전까지 테이블에 반영되지 않는다.
-> 예시
@Entity // 해당 클래스는 엔티티 클래스다. -> jpa 관리 대상 엔티티가 된다.
public class Member {
@Id //
@GeneratedValue(strategy = GenerationType.SEQUENCE) // 식별자 생성 전략
...
}
@Configuration
public class JpaIdDirectMappingConfig {
private EntityManager em;
private EntityTransaction tx;
@Bean
public CommandLineRunner testJpaSingleMappingRunner(EntityManagerFactory emFactory) {
this.em = emFactory.createEntityManager();
this.tx = em.getTransaction();
return args -> {
// SEQUENCE 전략
tx.begin();
em.persist(new Member());
Member member = em.find(Member.class, 1L);
System.out.println("# memberId : " + member.getMemberId());
tx.commit();
};
}
}
-> 결과
Hibernate: drop table if exists member CASCADE
Hibernate: drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
...
Hibernate: call next value for hibernate_sequence
# memberId : 1
Hibernate: insert into member (email, name, phone, member_id) values (?, ?, ?, ?)