====== 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]]