Reputation: 2063
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] including the main method i invoke and with the following mapping [2]. The issue about this approach you can see, when you look at the console output.
false
false
1
-1
1224754335648
1224754335000
Thu Oct 23 11:32:15 CEST 2008
Clock@67064
As you can see the the to dates are not exactly equal, although they should, so it is hard to compare them without goofing around with return value of getTime
. I also tried java.sql.Date, Timestamp and date instead of timestamp in the mapping, but without success.
I wonder why the last three digits are zero and if this is a hibernate or a java issue or my own stupidity.
Thank you for reading.
[1]
public class Clock {
int id;
java.util.Date date;
public static void main(String[] args) {
HibernateUtil.init();
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
Clock clock = new Clock();
clock.date = new java.util.Date();
HibernateUtil.getSessionFactory().getCurrentSession().saveOrUpdate(clock);
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
Clock fromDBClock = (Clock)HibernateUtil.getSessionFactory()
.getCurrentSession().get(Clock.class, 1);
System.out.println(clock.date.equals(fromDBClock.date));
System.out.println(fromDBClock.date.equals(clock.date));
System.out.println(clock.date.compareTo(fromDBClock.date));
System.out.println(fromDBClock.date.compareTo(clock.date));
System.out.println(clock.date.getTime());
System.out.println(fromDBClock.date.getTime());
System.out.println(clock.date.toString());
System.out.println(fromDBClock.toString());
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
HibernateUtil.end();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
}
[2]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Clock" table="CLOCK">
<id name="id" column="CLOCK_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp"/>
</class>
</hibernate-mapping>
Upvotes: 4
Views: 4895
Reputation: 8963
Personnaly, I truncate every date I receive in my POJO object with the Apache commons lang package class named DateUtils.
See [Apache commons site][1]
Upvotes: 0
Reputation: 7760
MySql DateTime precision is only to the second. Java Date precision is to the millisecond. That is why the last three digits are zeros after it has been put in the database.
Do this to your original Date:
date = date.setTime((date.getTime() / 1000) * 1000);
This will set it to the last exact second, and all your comparisons will then match.
(BTW, System.out.println(fromDBClock.toString()); should be System.out.println(fromDBClock.date.toString());
Upvotes: 5
Reputation: 13734
SQL Server stores datetime with a precision of 3 milliseconds which can definitely cause the problem you're seeing. One fallout of this is that 23:59:59.999 in Java ends up being the next day in SQL Server. I've never had a problem with Oracle, Informix, or MySQL, but other databases may have less precision also. You can work around it by using Hibernate custom types. You have to round to something less precise than the underlying database precision when you write out the date values. Search for UserType in the Hibernate documentation, you'll be changing the nullSafeSet method to do the rounding.
Upvotes: 2
Reputation: 18336
Apparently, TIMESTAMP type on your target RDBMS (what are you using, btw?) doesn't store milliseconds. Try to find another native type that does, or map your time onto something else, like long = ms-since-epoch.
Upvotes: 1