JVM/JPA

[JPA] 기본 키 전략과 Entity Custom ID Generator 구현하기

헹창 2022. 8. 5.
반응형

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
반응형

댓글

추천 글