====== Hibernate Primary Key (ID) Generator ======
* [[https://www.thoughts-on-java.org/custom-sequence-based-idgenerator/|How to Implement a Custom, Sequence-Based IdGenerator]]
* [[https://www.objectdb.com/java/jpa/entity/generated|JPA Generated Values (@GeneratedValue, @SequenceGenerator, @TableGenerator)]]
===== hibernate.id.new_generator_mappings =====
* 최신버전에서는 ''hibernate.id.new_generator_mappings=true'' 프라퍼티를 통해 JPA에 호환성에 부합하는 새로운 방식으로 ID를 생성할 수 있다. 보통은 이 값이 true이면 sequence 시도 안되면 table 시도로 선택한다.
* 구버전과의 호환성을 위한 것이 아니면 이 값을 **항상 ''true''**로 주고, MySQL 등 AUTO INCREMENT 계열에서는 ID 생성 방식을 ''AUTO''보다는 **구체적으로 IDENTITY로 명시**하도록 하자.
* [[http://in.relation.to/2082.lace|In Relation To... New (3.2.3) Hibernate identifier generators]]
* [[http://java.dzone.com/articles/jpa-hibernates-legacy-and|From JPA to Hibernate's Legacy and Enhanced Identifier Generators]]
* [[https://www.popit.kr/%ED%95%98%EC%9D%B4%EB%B2%84%EB%84%A4%EC%9D%B4%ED%8A%B8%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%90%EB%8F%99-%ED%82%A4-%EC%83%9D%EC%84%B1-%EC%A0%84%EB%9E%B5%EC%9D%84-%EA%B2%B0%EC%A0%95%ED%95%98/|하이버네이트는 어떻게 자동 키 생성 전략을 결정하는가 | Popit]]
===== UUID =====
* [[https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html|UUID]] ID 는 기본적으로 **Binary**로 매핑된다.
* 또한 ID Generator는 [[https://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/id/UUIDGenerator.html|UUIDGenerater]]를 사용한다.
* 해당 컬럼을 문자열로 지정하고 싶다면 ''@Type(type="uuid-char")''를 붙인다.
===== 기본 Custom Generator들 =====
* [[https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/id/factory/internal/DefaultIdentifierGeneratorFactory.java|org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory]] 에서 Hibernate가 제공하는 기본 Custom Generator 목록을 볼 수 있다.
==== Sequence에 대한 변화 ====
* 기존방식 : [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/id/SequenceHiLoGenerator.html|SequenceHiLoGenerator]] ID 생성시 모든 ID마다 Sequence 생성 호출
* 새 방식 : [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/id/enhanced/SequenceStyleGenerator.html|SequenceStyleGenerator]] 새로운 Sequence ID 생성방식. 한번 호출로 여러 Sequence를 생성하여 최적화하는 듯. 좀 더 확인 필요.
==== Table Generator에 대한 변화 ====
* 기존방식 : [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/id/TableHiLoGenerator.html|TableHiLoGenerator]]
* 새 방식 : [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/id/MultipleHiLoPerTableGenerator.html|MultipleHiLoPerTableGenerator]]
===== Identity (Auto Increment) =====
@Entity
public class EntityWithIdentityId {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) Long id;
:
}
* DB에서 ID 값을 읽어와야만 Persistence Context 에 저장가능하기 때문에, 객체 생성후 ''persist()'' 즉시 commit을 하지 않아도 DB 저장이 일어난다.
===== Sequence =====
@Entity
// Define a sequence - might also be in another class:
@SequenceGenerator(name="seq", initialValue=1, allocationSize=100)
public class EntityWithSequenceId {
// Use the sequence that is defined above:
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
@Id Long id;
}
===== Table =====
@Entity
@TableGenerator(name="tab", initialValue=0, allocationSize=50)
public class EntityWithTableId {
@GeneratedValue(strategy=GenerationType.TABLE, generator="tab")
@Id Long id;
}
===== IdGenerator =====
* ID 생성기를 Custom으로 만들 수 있다.
* [[https://vladmihalcea.com/how-to-implement-a-custom-string-based-sequence-identifier-generator-with-hibernate/|How to implement a custom String-based sequence identifier generator with Hibernate - Vlad Mihalcea]]
* [[http://blog.anorakgirl.co.uk/2009/01/custom-hibernate-sequence-generator-for-id-field/|Custom Hibernate Sequence Generator for Id field]]
* [[http://stackoverflow.com/questions/11631800/hibernate-how-specify-custom-sequence-generator-class-name-using-annotations|jpa - Hibernate: How specify custom sequence generator class name using annotations?]]
* [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/id/IdentifierGenerator.html|IdentifierGenerator]]를 상속하여 Custom Generator를 만들고
public class StockCodeGenerator implements IdentifierGenerator {
private static Logger log = Logger.getLogger(StockCodeGenerator.class);
public Serializable generate(SessionImplementor session, Object object)
throws HibernateException {
String prefix = "M";
// 이 Connection 은 Hibernate 가 관리하기 때문에 직접 close는 하지 말것.
Connection connection = session.connection();
try {
PreparedStatement ps = connection
.prepareStatement("SELECT nextval ('seq_stock_code') as nextval");
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int id = rs.getInt("nextval");
String code = prefix + StringUtils.leftPad("" + id,3, '0');
log.debug("Generated Stock Code: " + code);
return code;
}
} catch (SQLException e) {
log.error(e);
throw new HibernateException(
"Unable to generate Stock Code Sequence");
}
return null;
}
}
* 다음과 같은 방식으로 등록해서 사용한다.
@Id
@GenericGenerator(name="seq_id", strategy="my.package.StockCodeGenerator")
@GeneratedValue(generator="seq_id")
@Column(name = "stock_code", unique = true, nullable = false, length = 20)
public String getStockCode() {
return this.stockCode;
}
* ''org.hibernate.id.Configurable'' 인터페이스를 함께 구현하여 [[https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/annotations/GenericGenerator.html|@GenericGenerator]]에 파라미터를 지정하는 것도 가능하다. 이를 자신이 만든 Generator에서 받아서 사용한다.
===== 참조 =====
* [[https://www.baeldung.com/hibernate-identifiers|An Overview of Identifiers in Hibernate/JPA | Baeldung]]