Posts Tagged ‘ Hibernate

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);
		}
	}	
}

Read more

How to create custom order by in hibernate Criteria API

สืบเนื่องจากการใช้งาน Hibernate กับฐานข้อมูล oracle แล้วเจอปัญหาเวลาทำการเรียงลำดับข้อมูล (Order by) แล้วภาษาไทยจะเรียงไม่ถูกใจผู้ใช้งาน เช่น
การเรียงข้อมูลจังหวัด

กรุงเทพ
เชียงราย
เชียงใหม่
พะเยา
อ่างทอง

ข้อมูลจะถูกเรียงลำดับดังนี้

กรุงเทพ
พะเยา
อ่างทอง
เชียงราย
เชียงใหม่

ถ้าต้องการเรียงให้ถูกต้องตามหลักภาษาไทย (ภาษาไทยเทพเกิน) ต้องเพิ่ม function NLSSORT เข้าไปด้วยดังนี้

SELECT PROVINCE_NAME 
FROM CONF_PROVINCE
ORDER BY NLSSORT(PROVINCE_NAME, 'NLS_SORT = THAI_DICTIONARY');

ทุกอย่างเหมือนไม่มีอะไรซับซ้อนแต่ปัญหาก็คือ ระบบใช้ Hibernate และก็ Qurey ผ่าน Hibernate Criteria หลังจากสอบถาม google ก็ไปเจอกับแนวทางดังนี้
Read more

ORA-00932: inconsistent datatypes: expected NUMBER got BINARY

ใช้ Hibernate query ข้อมูลแล้วเจอ error

java.sql.SQLSyntaxErrorException: ORA-00932: inconsistent datatypes: expected NUMBER got BINARY

นึกสงสัยทำไมเกิด error เพราะ method นี้ถูกเรียกจากที่อื่นก็ไม่มีปัญหาอะไร เลยลอง debug โปรแกรมดู ปัญหาเกิดจากมีการส่ง parameter ที่เป็น null ให้กับ Hibernate query

[Java] ปัญหา Calendar ไม่แสดง ค.ศ ใน Weblogic Workshop 8.1

ปัญหาเล็กๆน้อยๆ แต่ทำเสียเวลาไปเกือบ 1 ชม.เต็มๆ ปัญหาก็เกิดจากการ query ข้อมูลจากฐานข้อมูลโดยใช้ HQL (Hibernate Query Language) และ เงื่อนไขดันใช้ Calendar ในการดึงข้อมูล ดังนี้

Calendar cal = Calendar.getInstance(Locale.US);
String hql = "from Order or where or.orderDate = ?";
Object values[] = new Object[] { cal};
Type type[] = new Type[] {TypeFactory.basic(Calendar.class.getName()) };
List orders = HibernateUtil.findBy(hql, values, type);

ทำอย่างไงก็ไม่ไ่ด้ข้อมูล ก็ งง อยู่พักหนึ่งว่าทำไมไม่ได้ ทั้งๆที่มีข้อมูล และ code บนเครื่อง production ก็ทำงานได้ปกติ พอเอามารันในเครื่องกับไม่ไ่ด้ ก็เลยลอง debug ดู เจอปัญหาเลย

มันดันเป็นปี พ.ศ ไปซะงั้น ลองกำหนดค่าต่างๆแล้วก็ไม่สามารถ format เป็น ค.ศ ได้ สุดท้ายต้องไปแก้ไข Reginal and Language Options ใน Control Pannel ดังรูป และ Restart มาก็เป็นการแก้ไขปัญหาเรียบร้อย

หมายเหตุ : เป็นการแก้ไขที่ยอมรับไม่ค่อยได้เท่าไร เพราะ ผมลองใน Eclipse, Netbeans ก็ใช้ได้ไม่มีปัญหาอะไร ยกเว้น Weblogic Workshop ต้องไปกำหนดตรงไหนกันแน่ ใครทราบช่วยแนะนำด้วยครับ