Custom Hibernate Sequence and JPA ID generator

หัวข้อนี้ก็ยังหนีไม่พ้น Hibernate อีกตามเคยจากหัวข้อที่แล้ว เรื่องการสร้าง custom order by หัวข้อนี้กลับมาดูเรื่องการ Custom การสร้าง ID และ Sequence แบบฉบับตามใจคนใช้งาน
เริ่มแรกก็ขอคววามช่วยเหลือจาก google ตามเคย หลังจากสอบถามก็ได้ข้อมูลมาสองที่ดังนี้
Customize IdGenerator in JPA, gap between Hibernate and JPA annotations และ
Custom Hibernate Sequence Generator for id field
เมื่อได้แหล่งข้อมูลตัวอย่างแล้วก็นำมาปรับแก้ดังนี้

/*
 * ----------------------------------------------------------------------------
 * Copyright © 2014 by http://www.secondknow.com. All rights reserved.
 * ----------------------------------------------------------------------------
 */
package com.secondknow.hibernate.seq;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Supot Saelao
 * @version 1.0
 */
public class OracleSeqWithDateFormatGenerator extends SequenceGenerator {
	private static final Logger logger = LoggerFactory.getLogger(OracleSeqWithDateFormatGenerator.class);
	
	private String sql;
	
	@Override
	public void configure(Type type, Properties params, Dialect dialect)
			throws MappingException {
		super.configure(type, params, dialect);
		
		String sequenceName = " TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') || " + getSequenceName();
		sql = dialect.getSequenceNextValString(sequenceName);
	}

	@Override
	public Serializable generate(SessionImplementor session, Object obj)
			throws HibernateException {
		return generateSeqStr(session);
	}
	
	private String generateSeqStr(SessionImplementor session) {
		try {
			logger.info("Seq statement : {}", sql);
			
			PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
			try {
				ResultSet rs = st.executeQuery();
				try {
					rs.next();
					String seqStr = rs.getString(1);
					logger.info("Seq value : {}", seqStr);
					
					return seqStr;
				} finally {
					rs.close();
				}
			} finally {
				session.getBatcher().closeStatement(st);
			}
		} catch (SQLException sqle) {
			throw JDBCExceptionHelper.convert(session.getFactory()
					.getSQLExceptionConverter(), sqle, "could not get next sequence value", sql);
		}
	}	
}


โดยรูปแบบของเลขที่ต้องการสร้างคือ เอาวันเดือนปี ชั่วโมงนาทีวินาที มารวมกับหมายเลข Seq จาก Orcale อีกที วิธีการก็คือการ overrid method “configure” และ “generate” จากนั้นไปเขียน code จัดการต่อใน method “generateSeqStr” เมื่อนำไปใช้งาน
ตัว OracleSeqWithDateFormatGenerator จะทำการนำเอา Oracle Seq มาต่อกับวันทีเป็นคำสั่ง sql ประมาณนี้

SELECT TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') || MY_SEQ.nextval FROM dual;

ส่วนการนำไปใช้ก็ตาม code ด้านล่างนี้เลย

/*
 * ----------------------------------------------------------------------------
 * Copyright © 2014 by http://www.secondknow.com. All rights reserved.
 * ----------------------------------------------------------------------------
 */
package com.secondknow.entities;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

import com.secondknow.entities.TransientAttribute;

/**
 * @author Supot Saelao
 * @version 1.0
 */
@Entity
@Table(name = "OCCUPANCY_RATE")
public class OccupancyRate extends TransientAttribute {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(generator = "oracleSeqStr")
    @GenericGenerator(name = "oracleSeqStr"
    	, strategy = "com.secondknow.hibernate.seq.OracleSeqWithDateFormatGenerator"
    	, parameters = {@Parameter(name = "sequence", value = "HIBERNATE_ID_SEQ")}
    )     
    @Basic(optional = false)
    @Column(name = "OCCUPANCY_RATE_ID")
    private String occupancyRateId;
    
    @Column(name = "REPORT_TYPE")
    private String reportType;

	//get & set method
}

แหล่งข้อมูล
Customize IdGenerator in JPA, gap between Hibernate and JPA annotations และ
Custom Hibernate Sequence Generator for id field

  1. No comments yet.

  1. No trackbacks yet.