How to force Hibernate to return dates as java.util.Date instead of Timestamp?
NickName:dim1902 Ask DateTime:2012-03-02T21:16:05

How to force Hibernate to return dates as java.util.Date instead of Timestamp?

Situation:

I have a persistable class with variable of java.util.Date type:

import java.util.Date;

@Entity
@Table(name = "prd_period")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Period extends ManagedEntity implements Interval {

   @Column(name = "startdate_", nullable = false)
   private Date startDate;

}

Corresponding table in DB:

CREATE TABLE 'prd_period' (
  'id_' bigint(20) NOT NULL AUTO_INCREMENT,
 ...
  'startdate_' datetime NOT NULL
)

Then I save my Period object to DB:

Period p = new Period();
Date d = new Date();
p.setStartDate();
myDao.save(p);

After then if I'm trying to extract my object from DB, it is returned with variable startDate of Timestamp type - and all the places where I'm trying to use equals(...) are returning false.

Question: are there any means to force Hibernate to return dates as object of java.util.Date type instead of Timestamp without explicit modification of every such variable (e.g it must be able just work, without explicit modification of existed variables of java.util.Date type)?

NOTE:

I found number of explicit solutions, where annotations are used or setter is modified - but I have many classes with Date-variables - so I need some centralized solution and all that described below is not good enough:

  1. Using annotation @Type: - java.sql.Date will be returned

    @Column
    @Type(type="date")
    private Date startDate;
    
  2. Using annotation @Temporal(TemporalType.DATE) - java.sql.Date will be returned

    @Temporal(TemporalType.DATE)
    @Column(name=”CREATION_DATE”)
    private Date startDate;
    
  3. By modifying setter (deep copy) - java.util.Date will be returned

    public void setStartDate(Date startDate) {
        if (startDate != null) {
            this.startDate = new Date(startDate.getTime());
        } else {
            this.startDate = null;
        }
    }
    
  4. By creation of my own type: - java.util.Date will be returned

Details are given here: http://blogs.sourceallies.com/2012/02/hibernate-date-vs-timestamp/

Copyright Notice:Content Author:「dim1902」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/9533935/how-to-force-hibernate-to-return-dates-as-java-util-date-instead-of-timestamp

Answers
Ilya Bystrov 2015-02-18T12:47:26

Here is solution for Hibernate 4.3.7.Final.\n\npacakge-info.java contains\n\n@TypeDefs(\n {\n @TypeDef(\n name = \"javaUtilDateType\",\n defaultForType = java.util.Date.class,\n typeClass = JavaUtilDateType.class\n )\n })\npackage some.pack;\nimport org.hibernate.annotations.TypeDef;\nimport org.hibernate.annotations.TypeDefs;\n\n\nAnd JavaUtilDateType:\n\npackage some.other.or.same.pack;\n\nimport java.sql.Timestamp;\nimport java.util.Comparator;\nimport java.util.Date;\nimport org.hibernate.HibernateException;\nimport org.hibernate.dialect.Dialect;\nimport org.hibernate.engine.spi.SessionImplementor;\nimport org.hibernate.type.AbstractSingleColumnStandardBasicType;\nimport org.hibernate.type.LiteralType;\nimport org.hibernate.type.StringType;\nimport org.hibernate.type.TimestampType;\nimport org.hibernate.type.VersionType;\nimport org.hibernate.type.descriptor.WrapperOptions;\nimport org.hibernate.type.descriptor.java.JdbcTimestampTypeDescriptor;\nimport org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;\n\n/**\n * Note: Depends on hibernate implementation details hibernate-core-4.3.7.Final.\n *\n * @see\n * <a href=\"http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch06.html#types-custom\">Hibernate\n * Documentation</a>\n * @see TimestampType\n */\npublic class JavaUtilDateType\n extends AbstractSingleColumnStandardBasicType<Date>\n implements VersionType<Date>, LiteralType<Date> {\n\n public static final TimestampType INSTANCE = new TimestampType();\n\n public JavaUtilDateType() {\n super(\n TimestampTypeDescriptor.INSTANCE,\n new JdbcTimestampTypeDescriptor() {\n\n @Override\n public Date fromString(String string) {\n return new Date(super.fromString(string).getTime());\n }\n\n @Override\n public <X> Date wrap(X value, WrapperOptions options) {\n return new Date(super.wrap(value, options).getTime());\n }\n\n }\n );\n }\n\n @Override\n public String getName() {\n return \"timestamp\";\n }\n\n @Override\n public String[] getRegistrationKeys() {\n return new String[]{getName(), Timestamp.class.getName(), java.util.Date.class.getName()};\n }\n\n @Override\n public Date next(Date current, SessionImplementor session) {\n return seed(session);\n }\n\n @Override\n public Date seed(SessionImplementor session) {\n return new Timestamp(System.currentTimeMillis());\n }\n\n @Override\n public Comparator<Date> getComparator() {\n return getJavaTypeDescriptor().getComparator();\n }\n\n @Override\n public String objectToSQLString(Date value, Dialect dialect) throws Exception {\n final Timestamp ts = Timestamp.class.isInstance(value)\n ? (Timestamp) value\n : new Timestamp(value.getTime());\n // TODO : use JDBC date literal escape syntax? -> {d 'date-string'} in yyyy-mm-dd hh:mm:ss[.f...] format\n return StringType.INSTANCE.objectToSQLString(ts.toString(), dialect);\n }\n\n @Override\n public Date fromStringValue(String xml) throws HibernateException {\n return fromString(xml);\n }\n}\n\n\nThis solution mostly relies on TimestampType implementation with adding additional behaviour through anonymous class of type JdbcTimestampTypeDescriptor.",


flexJavaMysql 2012-03-03T23:14:37

There are some classes in the Java platform libraries that do extend an instantiable\nclass and add a value component. For example, java.sql.Timestamp\nextends java.util.Date and adds a nanoseconds field. The equals implementation\nfor Timestamp does violate symmetry and can cause erratic behavior if\nTimestamp and Date objects are used in the same collection or are otherwise intermixed.\nThe Timestamp class has a disclaimer cautioning programmers against\nmixing dates and timestamps. While you won’t get into trouble as long as you\nkeep them separate, there’s nothing to prevent you from mixing them, and the\nresulting errors can be hard to debug. This behavior of the Timestamp class was a\nmistake and should not be emulated.\n\ncheck out this link\n\nhttp://blogs.sourceallies.com/2012/02/hibernate-date-vs-timestamp/",


ZiOS 2017-02-15T16:20:37

Just add the this annotation @Temporal(TemporalType.DATE) for a java.util.Date field in your entity class.\n\nMore information available in this stackoverflow answer.",


wbdarby 2014-07-30T17:24:08

I ran into a problem with this as well as my JUnit assertEquals were failing comparing Dates to Hibernate emitted 'java.util.Date' types (which as described in the question are really Timestamps). It turns out that by changing the mapping to 'date' rather than 'java.util.Date' Hibernate generates java.util.Date members. I am using an XML mapping file with Hibernate version 4.1.12.\n\nThis version emits 'java.util.Timestamp':\n\n<property name=\"date\" column=\"DAY\" type=\"java.util.Date\" unique-key=\"KONSTRAINT_DATE_IDX\" unique=\"false\" not-null=\"true\" />\n\n\nThis version emits 'java.util.Date':\n\n<property name=\"date\" column=\"DAY\" type=\"date\" unique-key=\"KONSTRAINT_DATE_IDX\" unique=\"false\" not-null=\"true\" />\n\n\nNote, however, if Hibernate is used to generate the DDL, then these will generate different SQL types (Date for 'date' and Timestamp for 'java.util.Date').",


dim1902 2012-03-06T11:13:03

So, I spent some time with this issue and found a solution. It is not pretty one, but at least a start point - maybe someone will supplement this with some useful comments.\n\nSome info about mapping that I found in process:\n\n\nClass that contains basic mapping of Hibernate types to property types is org.hibernate.type.TypeFactory. All this mappings are stored in unmodifiable map \n\nprivate static final Map BASIC_TYPES;\n...\nbasics.put( java.util.Date.class.getName(), Hibernate.TIMESTAMP );\n...\nBASIC_TYPES = Collections.unmodifiableMap( basics );\n\n\n\nAs you can see with java.util.Date type assosited with Hibernate type org.hibernate.type.TimestampType\n\n\nNext interesting moment - creation of Hibernate org.hibernate.cfg.Configuration - object that contains all info about mapped classes. This classes and their properties can be extracted like this:\n\nIterator clsMappings = cfg.getClassMappings();\nwhile(clsMappings.hasNext()){\n PersistentClass mapping = (PersistentClass) clsMappings.next();\n handleProperties(mapping.getPropertyIterator(), map);\n}\n\nVast majority of properties are the objects of org.hibernate.mapping.SimpleValue types. Our point of interest is the method SimpleValue.getType() - in this method is defined what type will be used to convert properties values back-and-forth while working with DB\n\nType result = TypeFactory.heuristicType(typeName, typeParameters);\n\n\n\nAt this point I understand that I am unable to modify BASIC_TYPES - so the only way - to replace SimpleValue object to the properties of java.util.Date types to my custom Object that will be able to know the exact type to convert.\n\nThe solution:\n\n\nCreate custom container entity manager factory by extending HibernatePersistence class and overriding its method createContainerEntityManagerFactory:\n\npublic class HibernatePersistenceExtensions extends HibernatePersistence {\n\n @Override\n public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) {\n\n if (\"true\".equals(map.get(\"hibernate.use.custom.entity.manager.factory\"))) {\n return CustomeEntityManagerFactoryFactory.createCustomEntityManagerFactory(info, map);\n } else {\n return super.createContainerEntityManagerFactory(info, map);\n }\n }\n}\n\nCreate Hibernate configuration object, modify value ojects for java.util.Date properties and then create custom entity manager factory.\n\npublic class ReattachingEntityManagerFactoryFactory {\n\n\n @SuppressWarnings(\"rawtypes\")\n public static EntityManagerFactory createContainerEntityManagerFactory(\n PersistenceUnitInfo info, Map map) {\n Ejb3Configuration cfg = new Ejb3Configuration();\n\n Ejb3Configuration configured = cfg.configure( info, map );\n\n handleClassMappings(cfg, map);\n\n return configured != null ? configured.buildEntityManagerFactory() : null;\n }\n\n @SuppressWarnings(\"rawtypes\")\n private static void handleClassMappings(Ejb3Configuration cfg, Map map) {\n Iterator clsMappings = cfg.getClassMappings();\n while(clsMappings.hasNext()){\n PersistentClass mapping = (PersistentClass) clsMappings.next();\n handleProperties(mapping.getPropertyIterator(), map);\n }\n } \n\n\n\n private static void handleProperties(Iterator props, Map map) {\n\n while(props.hasNext()){\n Property prop = (Property) props.next();\n Value value = prop.getValue();\n if (value instanceof Component) {\n Component c = (Component) value;\n handleProperties(c.getPropertyIterator(), map);\n } else {\n\n handleReturnUtilDateInsteadOfTimestamp(prop, map);\n\n }\n }\n\n private static void handleReturnUtilDateInsteadOfTimestamp(Property prop, Map map) {\n if (\"true\".equals(map.get(\"hibernate.return.date.instead.of.timestamp\"))) {\n Value value = prop.getValue();\n\n if (value instanceof SimpleValue) {\n SimpleValue simpleValue = (SimpleValue) value;\n String typeName = simpleValue.getTypeName();\n if (\"java.util.Date\".equals(typeName)) {\n UtilDateSimpleValue udsv = new UtilDateSimpleValue(simpleValue);\n prop.setValue(udsv);\n }\n }\n }\n }\n\n}\n\n\n\nAs you can see I just iterate over every property and substitute SimpleValue-object for UtilDateSimpleValue for properties of type java.util.Date. This is very simple class - it implements the same interface as SimpleValue object, e.g org.hibernate.mapping.KeyValue. In constructor original SimpleValue object is passed - so every call to UtilDateSimpleValue is redirected to the original object with one exception - method getType(...) return my custom Type.\n\npublic class UtilDateSimpleValue implements KeyValue{\n\n private SimpleValue value;\n\n public UtilDateSimpleValue(SimpleValue value) {\n this.value = value;\n }\n\n public SimpleValue getValue() {\n return value;\n }\n\n @Override\n public int getColumnSpan() {\n return value.getColumnSpan();\n }\n\n ...\n\n @Override\n public Type getType() throws MappingException {\n final String typeName = value.getTypeName();\n\n if (typeName == null) {\n throw new MappingException(\"No type name\");\n }\n\n Type result = new UtilDateUserType();\n\n return result;\n }\n ...\n}\n\n\n\nAnd the last step is implementation of UtilDateUserType. I just extend original org.hibernate.type.TimestampType and override its method get() like this:\n\npublic class UtilDateUserType extends TimestampType{\n\n @Override\n public Object get(ResultSet rs, String name) throws SQLException {\n Timestamp ts = rs.getTimestamp(name);\n\n Date result = null;\n if(ts != null){\n result = new Date(ts.getTime());\n }\n\n return result;\n }\n}\n\n\n\nThat is all. A little bit tricky, but now every java.util.Date property is returned as java.util.Date without any additional modifications of existing code (annotations or modifying setters). As I find out in Hibernate 4 or above there is a much more easier way to substitute your own type (see details here: Hibernate TypeResolver). Any suggestions or criticism are welcome.",


Nathan 2012-12-02T22:17:26

A simple alternative to using a custom UserType is to construct a new java.util.Date in the setter for the date property in your persisted bean, eg:\n\nimport java.util.Date;\nimport javax.persistence.Entity;\nimport javax.persistence.Column;\n\n@Entity\npublic class Purchase {\n\n private Date date;\n\n @Column\n public Date getDate() {\n return this.date;\n }\n\n public void setDate(Date date) {\n // force java.sql.Timestamp to be set as a java.util.Date\n this.date = new Date(date.getTime());\n }\n\n}\n",


Michael Paesold 2012-03-02T23:17:34

Approaches 1 and 2 obviously don't work, because you get java.sql.Date objects, per JPA/Hibernate spec, and not java.util.Date. From approaches 3 and 4, I would rather choose the latter one, because it's more declarative, and will work with both field and getter annotations.\n\nYou have already laid out the solution 4 in your referenced blog post, as @tscho was kind to point out. Maybe defaultForType (see below) should give you the centralized solution you were looking for. Of course will will still need to differentiate between date (without time) and timestamp fields.\n\nFor future reference I will leave the summary of using your own Hibernate UserType here:\n\nTo make Hibernate give you java.util.Date instances, you can use the @Type and @TypeDef annotations to define a different mapping of your java.util.Date java types to and from the database.\n\nSee the examples in the core reference manual here.\n\n\nImplement a UserType to do the actual plumbing (conversion to/from java.util.Date), named e.g. TimestampAsJavaUtilDateType\nAdd a @TypeDef annotation on one entity or in a package-info.java - both will be available globally for the session factory (see manual link above). You can use defaultForType to apply the type conversion on all mapped fields of type java.util.Date.\n\n@TypeDef\n name = \"timestampAsJavaUtilDate\",\n defaultForType = java.util.Date.class, /* applied globally */\n typeClass = TimestampAsJavaUtilDateType.class\n)\n\nOptionally, instead of defaultForType, you can annotate your fields/getters with @Type individually:\n\n@Entity\npublic class MyEntity {\n [...]\n @Type(type=\"timestampAsJavaUtilDate\")\n private java.util.Date myDate;\n [...]\n}\n\n\n\nP.S. To suggest a totally different approach: we usually just don't compare Date objects using equals() anyway. Instead we use a utility class with methods to compare e.g. only the calendar date of two Date instances (or another resolution such as seconds), regardless of the exact implementation type. That as worked well for us.",


More about “How to force Hibernate to return dates as java.util.Date instead of Timestamp?” related questions

How to force Hibernate to return dates as java.util.Date instead of Timestamp?

Situation: I have a persistable class with variable of java.util.Date type: import java.util.Date; @Entity @Table(name = "prd_period") @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

Show Detail

Comparing hibernate-mapped dates?

How can i map a date from a java object to a database with Hibernate? I try different approaches, but i am not happy with them. Why? Let me explain my issue. I have the following class [1] includin...

Show Detail

Map Oracle timestamp type to java.sql.Timestamp or java.util.Date using Hibernate?

I have an existing database with hundreds of tables using TIMESTAMP(6) as the data type for some columns. When I reverse engineered this database using Hibernate, the Java type Serializable is use...

Show Detail

How to tell hibernate to create Date instead of timestamp in DB?

How can I tell hibernate that a Date should be created as a Date in postgres SQL database, and not as a timestamp? According to www.postgresql.org/docs/9.3/static/datatype-datetime.html Date should...

Show Detail

How to use a UserType to persist java.util.Date as LONG in Hibernate?

This is a follow-up to the question Hibernate to persist Dates as long One of the non-selected answers mentions the use of UserType. How exactly can a UserType be used to cause java.util.Date to be

Show Detail

How to convert Hibernate.TIMESTAMP to Date?

How to convert Hibernate.TIMESTAMP to java.util.Date format?

Show Detail

How to force hibernate to return proxy

I have a scenario where everything works fine in dev environment, but fails in production due to proxies being returned instead of actual entities. How can I force hibernate to return proxies so th...

Show Detail

How to compare objects with a Date variable (Hibernate)? java.util.Date vs java.sql.Timestamp

Environment: MySql 5.6.14 Spring MVC Hibernate I'm having problems to check if 2 objects are equal, and the problem is caused by de variable Date. I'm using Hibernate and it seems to be the prob...

Show Detail

How to use java.sql.Timestamp as real java.util.Date with JPA

I have a problem about the management of dates with milliseconds. I understand the need to use the TIMESTAMP to store milliseconds: @Temporal(TIMESTAMP) @Column(name="DATE_COLUMN", nullable = fals...

Show Detail

Compare Date object with a TimeStamp in Java

When I test this code: java.util.Date date = new java.util.Date(); java.util.Date stamp = new java.sql.Timestamp(date.getTime()); assertTrue(date.equals(stamp)); assertTrue(date.compareTo(stamp) ...

Show Detail