Java 比较hibernate映射的日期?
如何使用Hibernate将日期从java对象映射到数据库?我尝试了不同的方法,但我对它们不满意。为什么?让我解释一下我的问题。我有以下类[1],包括我调用的主方法和以下映射[2]。当您查看控制台输出时,您可以看到这种方法的问题 假的 假的 一, -一, 1224754335648 1224754335000 2008年10月23日星期四11:32:15 CEST Clock@67064 正如您所看到的,虽然to日期应该是相等的,但它们并不完全相等,因此如果不使用返回值Java 比较hibernate映射的日期?,java,hibernate,date,Java,Hibernate,Date,如何使用Hibernate将日期从java对象映射到数据库?我尝试了不同的方法,但我对它们不满意。为什么?让我解释一下我的问题。我有以下类[1],包括我调用的主方法和以下映射[2]。当您查看控制台输出时,您可以看到这种方法的问题 假的 假的 一, -一, 1224754335648 1224754335000 2008年10月23日星期四11:32:15 CEST Clock@67064 正如您所看到的,虽然to日期应该是相等的,但它们并不完全相等,因此如果不使用返回值getTime来进行比较,
getTime
来进行比较,就很难做到这一点。我还尝试在映射中使用java.sql.Date、Timestamp和Date代替Timestamp,但没有成功
我想知道为什么最后三位数字是零,这是一个hibernate还是java问题,还是我自己的愚蠢
谢谢你的阅读
[1]
[2]
显然,目标RDBMS上的时间戳类型(顺便说一句,您使用的是什么?)不会存储毫秒。请尝试找到另一种本机类型,或者将您的时间映射到其他类型,例如long=ms-since-epoch。SQL Server以3毫秒的精度存储日期时间,这肯定会导致您看到的问题。这样做的一个后果是,Java中的23:59:59.999最终成为SQL Server中的第二天。我从来没有遇到过Oracle、Informix或MySQL方面的问题,但其他数据库的精确度也可能较低。您可以通过使用Hibernate自定义类型来解决这个问题。当您写出日期值时,您必须舍入到低于基础数据库精度的精度。在Hibernate文档中搜索UserType,您将更改nullSafeSet方法以进行舍入。MySql日期时间精度仅为秒。Java日期精度为毫秒。
这就是为什么最后三位数字在被放入数据库后是零
在您的原始日期执行此操作:
date=date.setTime((date.getTime()/1000)*1000)
这会将其设置为最后一秒,然后所有比较都将匹配
(顺便说一句,
System.out.println(fromDBClock.toString());
应该是
System.out.println(fromDBClock.date.toString());Personnaly,我使用名为DateUtils的Apache commons lang包类截断POJO对象中收到的每个日期 请参阅[Apache commons站点][1]
[1] :,int)您使用的目标RDBMS是什么?不同的数据库对次秒时间戳解析的支持程度不同。当您从数据库获取时钟时,您已将id硬编码为1,您确定它与刚才保存的值对应吗?我使用MySql数据库。你指的是另一种本机类型吗?有些数据库有多种日期/时间数据类型。根据doc,MySQL中没有高精度的日期数据类型:(您唯一简单的选择是将datetime映射为毫秒到长的时间。如果您创建自定义类型,甚至转换都将是自动的。我也使用MySql。这就是问题发生的地方。嗯……奇怪。也许我必须设置一些
选项来允许这种精度?!快速解决方法:org.apache.commons.lang3.time.DateUtils.truncatedEquals(a,b,Calendar.SECOND);
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;
}
}
<?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>