반응형
JPA 기본키 생성 전략
- 관계형 데이터베이스에서 테이블은 각각의 행을 구별하는 기본키가 필요하다
- 기본키를 만들 때는 주민등록번호, 주문번호 같은 자연키 를 사용할 수도 있고,
논리적 의미가 하나도 없는 시퀀스와 같은 대체키를 사용할 수도 있다.
@GeneratedValue
- JPA Entity 에서 @GeneratedValue 어노테이션을 기본키 필드 위에 붙이면 기본키를 자동으로 생성해주는 전략을 사용할 수 있다.
전략은 크게 4가지 이다.
IDENTITY
- 기본키 생성을 hibernate가 아닌, 데이터베이스가 하도록 위임한다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ..
}
- 데이터 저장 후 commit 시점에 최적의 상황을 고려해, 쿼리를 실행시키는 것이 아닌 persist() 시점에서 insert 문이 바로 실행되고 DB 에서 기본키 값을 생성한다.
- 그리고 이 키 값을 가져와 JPA 1차 캐시에 (key, entity) 를 저장한다.
- 따라서 IDENTITY 옵션은 write-behind (쓰기지연) 기능을 무시한다.
SEQUENCE
- Hibernate 가 만들어주는 시퀀스를 사용한다
- 데이터베이스(Oracle 등)가 제공해주는 시퀀스 사용도 가능하다
@SequenceGenerator 등록이 필요하다
@Entity
@SequenceGenerator(
name = "MEMBER_SEQ_GENERATOR",
sequenceName = "MEMBER_SEQ",
initialValue = 1,
allocationSize = 50
)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
private Long id;
// ..
}
- persist() 시점, 데이터 저장 시 데이터베이스에서 시퀀스를 조회하여 JPA 1차 캐시에 (key, entity) 를 저장한다.
- DB에 시퀀스 조회하면 DB I/O 요청 비용이 생긴다.
- 대량의 insert 쿼리가 주로 발생하는 엔티티에 initialValue와 allocationSize를 조정함으로써 메모리에 미리 순번을 저장하도록 설정하는 것이 좋다
TABLE
- 키 생성용 테이블을 별도로 사용하여 키를 생성한다
- 성능이 좋지 않아, 실제 운영에서는 잘 사용되지 않는다고 한다.
@Entity
@TableGenerator(
name = "MEMBER_KEY_GENERATOR",
table = "MEMBER_KEYS",
sequenceName = "MEMBER_KEY",
initialValue = 1,
allocationSize = 50
)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_KEY_GENERATOR")
private Long id;
// ..
}
AUTO
- 말 그대로 "자동"으로 적절한 전략을 알아서 매핑시킨다
- @GeneratedValue 라고만 쓰면 기본으로 AUTO 옵션을 사용한다
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// ..
}
☆ UUID 자동생성 되도록 설정하기 ☆
- Custom ID Generator 만들기 위해 IdentifierGenerator, Configurable Class 구현하면 가능하다.
- 두 클래스 모두 org.hibernate.id 패키지에 있다
- IdentifierGenerator 클래스 : 실제로 ID를 생성하는 로직을 구현한다.
- Configurable 클래스 : ID 생성을 위해 필요한 속성 값을 처리한다.
예제 코드 - Entity
@Entity
public class Member {
@Id
@GenericGenerator(
name = "idGenerator",
// 전략을 정의한 클래스 Full Path 입력한다
strategy = "***.common.IdGenerator",
// UUID란 이름으로 넘길 파라미터 값을 정한다
parameters = @org.hibernate.annotations.Parameter(name = "UUID", value = "MEMBER")
)
@GeneratedValue(generator = "idGenerator") // 위에서 정의한 이름
@Column
private String memberId;
}
예제 코드 - IdGenerator
public class IdGenerator implements IdentifierGenerator, Configurable {
private String uuidPrefix;
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
// Entity에서 "UUID" 값으로 넘긴 파라미터 값을 세팅한다 (ex. MEMBER)
uuidPrefix = ConfigurationHelper.getString("UUID", params);
}
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
// "MEMBER" 파라미터를 prefix로 UUID 값을 만들어준다.
// 반환 값은 MEMBER-XXXXXXXXXX 와 같은 형태로 만들어지겠죠
return UUIDGenerator.generateUUID(uuidPrefix);
}
}
이렇게 만들면 Entity의 preifx 별로 UUID를 만들 수 있어 편리하다 !
728x90
반응형
'JVM > JPA' 카테고리의 다른 글
[JPA] N+1 발생 원인과 해결책 (3) | 2023.05.30 |
---|---|
[JPA] QueryDSL 소개 및 프로젝트 설정하기 (0) | 2023.05.25 |
[JPA] SpringBoot JPA 쿼리 로그 설정하기 (0) | 2022.07.27 |
[JPA] JpaRepository를 상속 받은 인터페이스는 @Repository 없이 어떻게 인스턴스화될까? (0) | 2022.07.26 |
댓글