Code:
package richard.customType;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
import org.hibernate.usertype.CompositeUserType;
/**
* Class Description
*
* @version 1.00 4/07/2006
* @author Richard Zhou
*/
public class FourPartsDate implements CompositeUserType {
private static final int[] TYPES = { Types.NUMERIC, Types.NUMERIC, Types.NUMERIC, Types.NUMERIC };
private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd");
public int[] sqlTypes() {
return TYPES;
}
public Class returnedClass() {
return Date.class;
}
public boolean equals(Object x, Object y) {
if (x == y)
return true;
if (x == null || y == null)
return false;
return ((int[]) x)[0] == (((int[]) y)[0])
&& ((int[]) x)[1] == (((int[]) y)[1])
&& ((int[]) x)[2] == (((int[]) y)[2])
&& ((int[]) x)[3] == (((int[]) y)[3]);
}
public Object deepCopy(Object x) {
if (x == null)
return null;
/*int[] result = new int[4];
int[] input = (int[]) x;
result[0] = input[0];
result[1] = input[1];
result[2] = input[2];
result[3] = input[3];*/
return new Date(((Date) x).getTime());
}
public boolean isMutable() {
return true;
}
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session,
Object owner) throws HibernateException, SQLException {
int first = ((Integer) Hibernate.INTEGER.nullSafeGet(rs, names[0])).intValue();
int second = ((Integer) Hibernate.INTEGER.nullSafeGet(rs, names[1])).intValue();
int third = ((Integer) Hibernate.INTEGER.nullSafeGet(rs, names[2])).intValue();
int fourth = ((Integer) Hibernate.INTEGER.nullSafeGet(rs, names[3])).intValue();
return getDateFromInts(first, second, third, fourth);
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
Date dateTime = (value == null) ? new Date() : (Date) value;
int[] ints = getIntArrayFromDate(dateTime);
Hibernate.INTEGER.nullSafeSet(st, Integer.valueOf(ints[0]), index);
Hibernate.INTEGER.nullSafeSet(st, Integer.valueOf(ints[1]), index + 1);
Hibernate.INTEGER.nullSafeSet(st, Integer.valueOf(ints[2]), index + 2);
Hibernate.INTEGER.nullSafeSet(st, Integer.valueOf(ints[3]), index + 3);
}
public String[] getPropertyNames() {
return new String[] { "century", "year", "month", "day" };
}
public Type[] getPropertyTypes() {
return new Type[] { Hibernate.INTEGER, Hibernate.INTEGER, Hibernate.INTEGER, Hibernate.INTEGER };
}
public Object getPropertyValue(Object component, int property) {
return getDatePartAsInt((Date)component, property);
}
public void setPropertyValue(Object component, int property, Object value) {
Date date = ((Date) component);
int val = ((Integer)value).intValue();
setDatePartAsInt(date, property, val);
}
public Object assemble(Serializable cached, SessionImplementor session, Object owner) {
return deepCopy(cached);
}
public Serializable disassemble(Object value, SessionImplementor session) {
return (Serializable) deepCopy(value);
}
public int hashCode(Object x) throws HibernateException {
return super.hashCode();
}
public Object replace(Object original, Object target, SessionImplementor session,
Object owner) throws HibernateException {
// TODO Auto-generated method stub
return null;
}
private Date getDateFromInts(int a , int b, int c, int d){
int[] result = {a, b, c, d};
return getDateFromIntArray(result);
}
private Date getDateFromIntArray(int[] result){
Date date = new Date();
if (result[0] == 0 && result[1] == 0 && result[2] == 0 && result[3] == 0)
return date;
int year = result[0] * 100 + result[1];
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, result[2]);
cal.set(Calendar.DAY_OF_MONTH, result[3]);
return date;
}
private int[] getIntArrayFromDate(Date date){
int[] result = new int[4];
if (date == null)
return result;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
result[0] = cal.get(Calendar.YEAR) / 100;
result[1] = cal.get(Calendar.YEAR) % 100;
result[2] = cal.get(Calendar.MONTH);
result[3] = cal.get(Calendar.DAY_OF_MONTH);
return result;
}
private Integer getDatePartAsInt(Date date, int index) {
if (date == null)
return new Integer(0);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
switch (index) {
case 0:
return new Integer(cal.get(Calendar.YEAR) / 100);
case 1:
return new Integer(cal.get(Calendar.YEAR) % 100);
case 2:
return new Integer(cal.get(Calendar.MONTH));
case 3:
return new Integer(cal.get(Calendar.DAY_OF_MONTH));
default:
return null;
}
}
private void setDatePartAsInt(Date date, int index, int value){
if (date == null)
return;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
switch (index) {
case 0:
break;
case 1:
int year = cal.get(Calendar.YEAR);
int cent = year - (year % 100);
cal.set(Calendar.YEAR, cent + value);
break;
case 2:
cal.set(Calendar.MONTH, value);
break;
case 3:
cal.set(Calendar.DAY_OF_MONTH, value);
break;
default:
break;
}
}
}
Hibernate version:
Hibernate 3.0
Mapping documents:
<hibernate-mapping package="richard.domain">
<class name="Expense" table="CREXP">
<id name="expenseId" type="java.lang.String">
<column name="EHEXP#" length="6"/>
</id>
<property name="employeeUserId" type="java.lang.String">
<column name="EHUSER" length="10"/>
</property>
<property name="expenseCreditor" type="java.lang.String">
<column name="EHICR" length="8"/>
</property>
<property name="expenseNarrative" type="java.lang.String">
<column name="EHNARR" length="30"/>
</property>
<property name="expenseTotals" type="java.lang.Double">
<column name="EHINVA" precision="11"/>
</property>
<property name="expenseGST" type="java.lang.Double">
<column name="EHGST" precision="11"/>
</property>
<property name="expenseDate" type="richard.customType.FourPartsDate">
<column name="EHIDCN"/>
<column name="EHIDYY"/>
<column name="EHIDMM"/>
<column name="EHIDDD"/>
</property>
<property name="ehstat" type="java.lang.String">
<column name="EHSTAT" length="1"/>
</property>
<property name="ehdta" type="java.lang.Long">
<column name="EHDTA" precision="6" scale="0"/>
</property>
<property name="ehdtc" type="java.lang.Long">
<column name="EHDTC" precision="6" scale="0"/>
</property>
<property name="ehusrc" type="java.lang.String">
<column name="EHUSRC" length="10"/>
</property>
<property name="ehstcn" type="java.lang.Long">
<column name="EHSTCN" precision="2" scale="0"/>
</property>
<property name="ehstyy" type="java.lang.Long">
<column name="EHSTYY" precision="2" scale="0"/>
</property>
<property name="ehstmm" type="java.lang.Long">
<column name="EHSTMM" precision="2" scale="0"/>
</property>
<property name="ehstdd" type="java.lang.Long">
<column name="EHSTDD" precision="2" scale="0"/>
</property>
<property name="ehauth" type="java.lang.String">
<column name="EHAUTH" length="10"/>
</property>
<property name="ehsqu" type="java.lang.Long">
<column name="EHSQU" precision="7" scale="0"/>
</property>
<property name="ehgkey" type="java.lang.Long">
<column name="EHGKEY" precision="9" scale="0"/>
</property>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
List result = session.createQuery("from Expense").list();
Full stack trace of any exception that occurs:
Save failed - exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of richard.domain.Expense.setExpenseDate
org.hibernate.PropertyAccessException: exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of richard.domain.Expense.setExpenseDate
at org.hibernate.tuple.PojoTuplizer.setPropertyValuesWithOptimizer(PojoTuplizer.java:203)
at org.hibernate.tuple.PojoTuplizer.setPropertyValues(PojoTuplizer.java:173)
at org.hibernate.persister.entity.BasicEntityPersister.setPropertyValues(BasicEntityPersister.java:2919)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:113)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:530)
at org.hibernate.loader.Loader.doQuery(Loader.java:436)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.doList(Loader.java:1593)
at org.hibernate.loader.Loader.list(Loader.java:1577)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:395)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:271)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:844)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:74)
at richard.HibernateTest.loadClientList(HibernateTest.java:69)
at richard.HibernateTest.main(HibernateTest.java:44)
Caused by: net.sf.cglib.beans.BulkBeanException: java.util.Date
at richard.domain.Expense$$BulkBeanByCGLIB$$f33f877a.setPropertyValues(<generated>)
at org.hibernate.tuple.PojoTuplizer.setPropertyValuesWithOptimizer(PojoTuplizer.java:200)
... 14 more
Caused by: java.lang.ClassCastException: java.util.Date
... 16 more
Name and version of the database you are using:
DB2 on AS400,
The generated SQL (show_sql=true):
Debug level Hibernate log excerpt: