Member Menu
 
 Monthly JBoss newsletter:
 
Hibernate Books
CaveatEmptor

UserType for non-default TimeZone

Hibernate's built-in date, time and timestamp types assume that dates in the database are in Java's default time zone, implicitly. If this assumption is false (and you can't make it true by calling java.util.TimeZone.setDefault), you can configure Hibernate to map to a UserType that does something else. For example, given a MS SQL Server database like:

CREATE TABLE ... (
    creationDate datetime NULL

or an Oracle database like:

CREATE TABLE ... (
    creationDate DATE

You can use a Hibernate mapping like:

<property name="creationDate" type="com.domain.HibernateUTC$DateType"/>

Here's an example implementation of the necessary Java software:

package com.domain;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;

/** Hibernate UserType definitions like date, time and timestamp,
 * but using the UTC TimeZone (not the default TimeZone).
 */
public abstract class HibernateUTC implements net.sf.hibernate.UserType {

    public static final int[] SQL_TYPES = {Types.TIMESTAMP};

    /** Get the type codes (from <code>java.sql.Types</code>) of columns mapped by this type. */
    public int[] sqlTypes()
    {
        return SQL_TYPES;
    }

    /** Compare the persistent state of two objects returned by <code>nullSafeGet</code>. */
    public boolean equals(Object x, Object y)
    {
        return (x == null) ? (y == null) : x.equals(y);
    }

    /** Are instances of this type mutable? */
    public boolean isMutable()
    {
        return true;
    }

    /** Get the class of objects returned by <code>nullSafeGet</code>. */
    public Class returnedClass()
    {
        return objectClass;
    }

    /** The class of objects returned by <code>nullSafeGet</code>.
     * Currently, returned objects are derived from this class, not exactly this class.
     */
    protected Class objectClass = Date.class;

    /** Like a Hibernate date, but using the UTC TimeZone (not the default TimeZone). */
    public static class DateType extends HibernateUTC {

        public Object deepCopy(Object value)
        {
            return (value == null) ? null : new java.sql.Date(((Date)value).getTime());
        }

        public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws SQLException
        {
            return rs.getDate(names[0], UTCCalendar.getCalendar());
        }

        public void nullSafeSet(PreparedStatement st, Object value, int index)
            throws SQLException
        {
            if ( ! (value instanceof java.sql.Date)) value = deepCopy(value);
            st.setDate(index, (java.sql.Date)value, UTCCalendar.getCalendar());
        }

    }

    /** Like a Hibernate time, but using the UTC TimeZone (not the default TimeZone). */
    public static class TimeType extends HibernateUTC {

        public Object deepCopy(Object value)
        {
            return (value == null) ? null : new java.sql.Time(((Date)value).getTime());
        }

        public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws SQLException
        {
            return rs.getTime(names[0], UTCCalendar.getCalendar());
        }

        public void nullSafeSet(PreparedStatement st, Object value, int index)
            throws SQLException
        {
            if ( ! (value instanceof java.sql.Time)) value = deepCopy(value);
            st.setTime(index, (java.sql.Time)value, UTCCalendar.getCalendar());
        }

    }

}

Note, the implementation above has a bug in it. The static SQL_TYPES 'overridden' in the inner subclasses are in fact not overridden, so the Type in the SQL_TYPE array returned by the 'sqlTypes' method will always be of type Types.TIMESTAMP. The fixed version of this code is posted below:

public abstract class HibernateUTC implements UserType {

    /** the SQL type this type manages */
    protected static int[] SQL_TYPES_UTC = {Types.TIMESTAMP};

    /**
     * @see net.sf.hibernate.UserType#sqlTypes()
     */
    public int[] sqlTypes() {        
        return SQL_TYPES_UTC;
    }

    /**
     * @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
     */
    public boolean equals(Object x, Object y) {
        return (x == null) ? (y == null) : x.equals(y);
    }

    /**
     * @see net.sf.hibernate.UserType#isMutable()
     */
    public boolean isMutable() {
        return true;
    }

    /**
     * @see net.sf.hibernate.UserType#returnedClass()
     */
    public Class returnedClass() {
        return objectClass;
    }

    /**
     * The class of objects returned by <code>nullSafeGet</code>. Currently,
     * returned objects are derived from this class, not exactly this class.
     */
    protected Class objectClass = Date.class;

    /**
     * Like a Hibernate date, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class DateType extends HibernateUTC {
        protected static int[] SQL_TYPES_DATE = {Types.DATE};

        /**
         * @see net.sf.hibernate.UserType#sqlTypes()
         */
        public int[] sqlTypes() {        
            return SQL_TYPES_DATE;
        }

       
        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Date(((Date) value).getTime());

        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getDate(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */
        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Date))
                value = deepCopy(value);
            st.setDate(index, (java.sql.Date) value, sUTCCalendar);
        }
    }

    /**
     * Like a Hibernate time, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class TimeType extends HibernateUTC {

        protected static int[] SQL_TYPES_TIME = {Types.TIME};

        /**
         * @see net.sf.hibernate.UserType#sqlTypes()
         */
        public int[] sqlTypes() {        
            return SQL_TYPES_TIME;
        }
       

        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Time(((Date) value).getTime());
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getTime(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */
        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Time))
                value = deepCopy(value);
            st.setTime(index, (java.sql.Time) value, sUTCCalendar);
        }
    }

    /**
     * Like a Hibernate timestamp, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class TimestampType extends HibernateUTC {

        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Timestamp(((Date) value).getTime());

        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getTimestamp(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */

        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Timestamp))
                value = deepCopy(value);
            st.setTimestamp(index, (java.sql.Timestamp) value, sUTCCalendar);
        }
    }

    /** the Calendar to hold the UTC timezone */
    private static Calendar sUTCCalendar=Calendar.getInstance();

    static {
        // set the timezone for the calendar to UTC (= GMT)
        sUTCCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));
    }
}

Regards,

Matt


One problem with the above approach (at least in Hibernate 2) is that HQL queries can "silently fail" if you forget to pass Hibernate.custom(...) as the parameter type for UTC dates. The time zone conversion isn't done.

Here's an alternative UserType that uses a BIGINT as the database data type. The value is the long representation of a java.util.Date. No silent failures here!

public class UtcDateTimeType implements UserType {

    
    /**
     * SQL type.
     */
    private static final int[] SQL_TYPES = { Types.BIGINT };
    
    /** 
     * Make a copy of the date.
     * @see UserType#deepCopy(java.lang.Object)
     */
    public Object deepCopy(Object obj) throws HibernateException {
        return (obj == null) ? null : new Date(((Date)obj).getTime());
    }
    
    /**
     * Compare via {@link Object#equals(java.lang.Object)}.
     * @see UserType#equals(java.lang.Object, java.lang.Object)
     */
    public boolean equals(Object x, Object y) {
        return (x == null) ? (y == null) : x.equals(y);
    }
    
    /**
     * Dates are mutable.
     * @see net.sf.hibernate.UserType#isMutable()
     */
    public boolean isMutable() {
        return true;
    }
    
    /**
     * Return an instance of the date or null if no value is specified.
     * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
     */
    public Object nullSafeGet(ResultSet rs, String[] columns, Object owner)
            throws HibernateException, SQLException {

        long value = rs.getLong(columns[0]);
        Date date;
        if(rs.wasNull()) {
            date = null;
        } else {
            date = new Date(value);
        }
        return date; 
        
    }

    /**
     * Set an instance of the date into the database field.
     * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
     */
    public void nullSafeSet(PreparedStatement statement, Object value, int index)
            throws HibernateException, SQLException {
        
        if(value == null) {
            statement.setNull(index, Types.BIGINT);
        } else {
            Date date = (Date)value;
            statement.setLong(index, date.getTime());
        }
    }
    
    /**
     * Return the {@link Date} class.
     * @see net.sf.hibernate.UserType#returnedClass()
     */
    public Class returnedClass() {
        return Date.class;
    }
    
    /**
     * Return the supported SQL types.
     * @see net.sf.hibernate.UserType#sqlTypes()
     */
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

}

For completeness, you could also write a routine that checks the mapping metadata at startup and throws an exception if a date property is not mapped using the user type. We do this to avoid accidental use of the build-in timestamp type.

Enjoy,

-Rob

======================================================================

Here is my modification to the above.

It is Hibernate3 compatible, which previous examples aren't, but word of caution, we don't use caching so I can't vouch for assemble and disassemble methods. The compiler accepts them, that's all I say. It adds a Calendar handler which is the big change.

-- Steve Cohen 10/13/2007

package com.domain;

import java.io.Serializable;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.TimeZone;

import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment;
import org.hibernate.usertype.UserType;

public abstract class HibernateUTC implements UserType {

    /** the SQL type this type manages */
    protected static int[] SQL_TYPES_UTC = {Types.TIMESTAMP};

    /**
     * @see net.sf.hibernate.UserType#sqlTypes()
     */
    public int[] sqlTypes() {        
        return SQL_TYPES_UTC;
    }

    /**
     * @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
     */
    public boolean equals(Object x, Object y) {
        return (x == null) ? (y == null) : x.equals(y);
    }

    /**
     * @see net.sf.hibernate.UserType#isMutable()
     */
    public boolean isMutable() {
        return true;
    }

    /**
     * @see net.sf.hibernate.UserType#returnedClass()
     */
    public Class returnedClass() {
        return objectClass;
    }

    /**
     * The class of objects returned by <code>nullSafeGet</code>. Currently,
     * returned objects are derived from this class, not exactly this class.
     */
    protected Class objectClass = Date.class;
    
    /**
     * Get a hashcode for the instance, consistent with persistence "equality"
     */
    public int hashCode(Object x) 
    throws HibernateException 
    {
        return x.hashCode();
    }
    
    /**
     * Transform the object into its cacheable representation. At the very least this
     * method should perform a deep copy if the type is mutable. That may not be enough
     * for some implementations, however; for example, associations must be cached as
     * identifier values. (optional operation)
     *
     * @param value the object to be cached
     * @return a cachable representation of the object
     * @throws HibernateException
     */
    public Serializable disassemble(Object value) 
    throws HibernateException
    {
        return (Serializable) deepCopy(value);
    }

    /**
     * Reconstruct an object from the cacheable representation. At the very least this
     * method should perform a deep copy if the type is mutable. (optional operation)
     *
     * @param cached the object to be cached
     * @param owner the owner of the cached object
     * @return a reconstructed object from the cachable representation
     * @throws HibernateException
     */
    public Object assemble(Serializable cached, Object owner) 
    throws HibernateException
    {
        return deepCopy(cached);
    }

    /**
     * During merge, replace the existing (target) value in the entity we are merging to
     * with a new (original) value from the detached entity we are merging. For immutable
     * objects, or null values, it is safe to simply return the first parameter. For
     * mutable objects, it is safe to return a copy of the first parameter. For objects
     * with component values, it might make sense to recursively replace component values.
     *
     * @param original the value from the detached entity being merged
     * @param target the value in the managed entity
     * @return the value to be merged
     */
    public Object replace(Object original, Object target, Object owner) 
    throws HibernateException 
    {
        return deepCopy(original);
    }



    /**
     * Like a Hibernate date, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class DateType extends HibernateUTC {
        protected static int[] SQL_TYPES_DATE = {Types.DATE};

        /**
         * @see net.sf.hibernate.UserType#sqlTypes()
         */
        public int[] sqlTypes() {        
            return SQL_TYPES_DATE;
        }

       
        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Date(((Date) value).getTime());

        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getDate(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */
        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Date))                
                value = deepCopy(value);
            st.setDate(index, (java.sql.Date) value, sUTCCalendar);
        }
    }

    /**
     * Like a Hibernate time, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class TimeType extends HibernateUTC {

        protected static int[] SQL_TYPES_TIME = {Types.TIME};

        /**
         * @see net.sf.hibernate.UserType#sqlTypes()
         */
        public int[] sqlTypes() {        
            return SQL_TYPES_TIME;
        }
       

        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Time(((Date) value).getTime());
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getTime(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */
        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Time))
                value = deepCopy(value);
            st.setTime(index, (java.sql.Time) value, sUTCCalendar);
        }
    }

    /**
     * Like a Hibernate timestamp, but using the UTC TimeZone (not the default
     * TimeZone).
     */
    public static class TimestampType extends HibernateUTC {

        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            return (value == null) ? null : new java.sql.Timestamp(((Date) value).getTime());

        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            return rs.getTimestamp(names[0], sUTCCalendar);
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */

        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (!(value instanceof java.sql.Timestamp))
                value = deepCopy(value);
            st.setTimestamp(index, (java.sql.Timestamp) value, sUTCCalendar);
        }
        
    }

    public static class CalendarType extends HibernateUTC {

        public Class getReturnedClass() {
            return Calendar.class;
        }

        /**
         * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
         */
        public Object deepCopy(Object value) {
            if (value == null) {
                return null;
            }
            Calendar c = (Calendar) sUTCCalendar.clone();
            c.setTimeInMillis(((Calendar) value).getTimeInMillis());
            return c;
        }

        /**
         * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
         */
        public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
            Timestamp ts = rs.getTimestamp(names[0], sUTCCalendar);
            if (ts == null || rs.wasNull() ) {
                return null;
            }
            Calendar cal = (Calendar) sUTCCalendar.clone();
            if ( Environment.jvmHasTimestampBug() ) {
                cal.setTime( new Date( ts.getTime() + ts.getNanos() / 1000000 ) );
            }
            else {
                cal.setTime(ts);
            }
            return cal;
            
        }


        /**
         * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
         */

        public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
            if (value == null) {
                st.setNull(index, Types.TIMESTAMP);
            } else {
                Timestamp t = new Timestamp(((Calendar) value).getTimeInMillis());
                st.setTimestamp(index, t, sUTCCalendar);
            }
        }
        
        /* (non-Javadoc)
         * @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object)
         */
        public boolean equals(Object x, Object y)
        {
            if (x==y) return true;
            if (x==null || y==null) return false;

            Calendar calendar1 = (Calendar) x;
            Calendar calendar2 = (Calendar) y;

            return calendar1.getTimeInMillis() == calendar2.getTimeInMillis();
        }
        /* (non-Javadoc)
         * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
         */
        public int hashCode(Object x)
            throws HibernateException
        {
            return new Long(((Calendar) x).getTimeInMillis()).hashCode();
        }
    }

    /**
     * Note 071107: passing the static sUTCCalendar instance to the 
     * setTimestamp(), getTimestamp() calls above has concurrency issues, 
     * as some JDBC drivers do modify the supplied calendar instance.
     * More defensive code should create a new Calendar instance in UTC
     * and pass it to each getTimestamp() / setTimestamp() call.
     *
     */

    /** the Calendar to hold the UTC timezone */
    private static Calendar sUTCCalendar=Calendar.getInstance();

    static {
        // set the timezone for the calendar to UTC (= GMT)
        sUTCCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
    }
}



  NEW COMMENT

What about multiple custom TimeZones? 14 Apr 2005, 12:23 rgutmann
Hello,

isn't the usual case - when a different timezone is needed - a bit more
complicated? E.g.: don't you usually have clients from all over the
world (each in their own timezone) bringing you dates to a central
appserver (with one central timezone) which then uses Hibernate to store
the data?

And, if you have fat clients which are acting this way, don't they query
objects in one session, then close the session (detaching the objects?)
and try to save the modified objects in one bunch in a new session
(reattached?)? Thus every session needs a customizable TimeZone, doesn't it?

A you might haved guessed by now, this is my current implementation
problem. Any ideas would be greatly appreciated. ;)

Best regards,

Ralph.
 
store timestamps in UTC in DB, use Calendar from Java 21 Jul 2005, 10:15 GeraldLoeffler
hi!

In case anybody is interested: Here is my take on this very common
problem of handling timestamps expressed in arbitrary timezones:

I understand that there is no easy and portable way to store timestamps
with timezone information in the database. Thus I'm using SQL type
TIMESTAMP (which has no timezone information) to store timestamp
information and normalize all timestamps in the database to UTC.

A UTC database timestamp is mapped as a Hibernate timestamp type to a
java.util.Date. A java.util.Date also has no timezone information.

However, the getter/setter for a timestamp property on the Java entity
type returns/takes a java.util.Calendar object. A java.util.Calendar
contains timezone information, thus to the client of the Java class
there can never be any doubt in which timezone a timestamp is expressed.

(I use Hibernate field access for the Hibernate mapping because of the
above.)

The setter immediately converts the Calendar timestamp to a
java.util.Date in UTC to set the entity's field. Conversely, the getter
constructs a java.util.Calendar with timezone UTC and initializes it
from the entity's field.

Thus, the information about the timezone in which the client originally
expressed a timestamp is lost, but the timezone handling is otherwise
correct.

  cheers,
  gerald
 
Is this still necessary? 03 Jan 2007, 22:31 pansapien
Is this still necessary?
 
Is the UserType still necessary in Hibernate 3.2? 06 Feb 2007, 02:02 weeder
The original post is dated 2004 and refers to Hibernate 2.x. I am 
wondering if the support of non-default timezone has been added to the 
later versions of Hibernate.
 
Re: store timestamps in UTC in DB, use Calendar from Java 19 Mar 2007, 01:58 boomreddy
POST QUESTIONS ON THE FORUM! COMMENTS HERE SHOULD ADD VALUE TO THE PAGE!
 
Re: store timestamps in UTC in DB, use Calendar from Java 21 Jan 2008, 05:14 wilfred
POST QUESTIONS ON THE FORUM! COMMENTS HERE SHOULD ADD VALUE TO THE
PAGE!On 19 Mar 2007 01:58, boomreddy wrote:

>POST QUESTIONS ON THE FORUM! COMMENTS HERE SHOULD ADD VALUE TO THE PAGE!



I wonder whether it is simpler and cleaner for the database to store the
"instant of time" information only, leaving the time zone matter to the
display functions (like Calendar). The Java Date and Calendar and
TimeZone classes take this approach. ?
 
How to specify user type in hbm file? 25 Apr 2008, 11:48 mtoohey
Hey Steve - I really like the implementation you posted for this user
type. I haven't tried static extension classes like that before - so I
learned something new in reviewing it.  When I tried to specify the user
type (the static extension) in my hbm, Hibernate couldn't parse and
create the mapping correctly.  Were you able to specify it in an hbm?
 
This is working great. We have one issue... 29 May 2008, 09:20 jcaristi
We have standardized on java.util.Calendar in our application, and 
HibernatUTC is working well for us, except that I am getting a 
ClassCastException when I attempt to use HibernateUTC with a version 
column.  The database is set to automatically generate a timestamp on 
insert or update. My Hibernate mapping looks like this:

<version name="lastUpdated" generated="always" 
type="whi.core.data.hibernate.HibernateUTC$CalendarType" 
column="LastUpdated"/>
	 
Even though I have generated="always" in my mapping file, if I do not 
initialize the data for this column in my application, Hibernate seems 
to be generating a "seed" value.  When it does, I get the error that 
follows. I would prefer to never set this column value (since it is 
database-generated) but for the moment, I am setting the value to the 
current date as a workaround.  I haven't taken the time to look into 
the Hibernate code to see what is going on.  

Here's the error:

java.lang.ClassCastException: 
whi.core.data.hibernate.HibernateUTC$CalendarType
	at org.hibernate.type.CustomType.seed(CustomType.java:203)
	at org.hibernate.engine.Versioning.seed(Versioning.java:55)
	at org.hibernate.engine.Versioning.seedVersion
(Versioning.java:86)
	at 
org.hibernate.event.def.AbstractSaveEventListener.substituteValuesIfNece
ssary(AbstractSaveEventListener.java:404)
	at 
org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate
(AbstractSaveEventListener.java:270)
	at 
org.hibernate.event.def.AbstractSaveEventListener.performSave
(AbstractSaveEventListener.java:181)
	at 
org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId
(AbstractSaveEventListener.java:107)
	at 
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGenerat
edOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
	at 
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransie
nt(DefaultSaveOrUpdateEventListener.java:172)
	at 
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUp
date(DefaultSaveOrUpdateEventListener.java:94)
	at 
org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate
(DefaultSaveOrUpdateEventListener.java:70)
	at org.hibernate.impl.SessionImpl.fireSaveOrUpdate
(SessionImpl.java:507)
	at org.hibernate.impl.SessionImpl.saveOrUpdate
(SessionImpl.java:499)
	at org.hibernate.impl.SessionImpl.saveOrUpdate
(SessionImpl.java:495)
	at 
org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate
(HibernateTemplate.java:696)
	at 
org.springframework.orm.hibernate3.HibernateTemplate.execute
(HibernateTemplate.java:373)
	at 
org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate
(HibernateTemplate.java:693)
 
© Copyright 2006, Red Hat Middleware, LLC. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc. [Privacy Policy]