【问题标题】:Comparing hibernate-mapped dates?比较休眠映射的日期?
【发布时间】:2010-09-18 18:03:57
【问题描述】:

如何使用 Hibernate 将日期从 java 对象映射到数据库?我尝试了不同的方法,但我对它们不满意。为什么?让我解释一下我的问题。我有以下类 [1],包括我调用的主要方法和以下映射 [2]。当您查看控制台输出时,您可以看到有关此方法的问题。

假的

1

-1

1224754335648

1224754335000

2008 年 10 月 23 日星期四 11:32:15 CEST

时钟@67064

正如您所看到的,截止日期并不完全相等,尽管它们应该相等,因此很难在没有返回值 getTime 的情况下比较它们。我还尝试了 java.sql.Date、Timestamp 和 date 而不是映射中的时间戳,但没有成功。

我想知道为什么最后三位数字为零,这是休眠还是 java 问题还是我自己的愚蠢。

感谢您的阅读。

[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>

【问题讨论】:

  • 您使用什么目标 RDBMS?不同的数据库对亚秒级时间戳分辨率的支持程度不同
  • 当您从数据库中获取时钟时,您已将 id 硬编码为 1,您确定这与您刚刚保存的值相对应吗?

标签: java hibernate date


【解决方案1】:

个人而言,我使用名为 DateUtils 的 Apache commons lang 包类截断我在 POJO 对象中收到的每个日期。

参见 [Apache 公共站点][1]

[1]:http://commons.apache.org/lang/api/org/apache/commons/lang/time/DateUtils.html#truncate(java.util.Date,整数)

【讨论】:

    【解决方案2】:

    MySql DateTime 精度仅为秒。 Java 日期精度为毫秒。 这就是为什么最后三位数字在放入数据库后为零的原因。

    对您的原始日期执行此操作:

    date = date.setTime((date.getTime() / 1000) * 1000);

    这会将其设置为最后一秒,然后您的所有比较都会匹配。

    (顺便说一句, System.out.println(fromDBClock.toString()); 应该 System.out.println(fromDBClock.date.toString());

    【讨论】:

    • 快速解决方法:org.apache.commons.lang3.time.DateUtils.truncatedEquals(a, b, Calendar.SECOND);
    【解决方案3】:

    SQL Server 以 3 毫秒的精度存储日期时间,这肯定会导致您看到的问题。这样做的一个后果是 Java 中的 23:59:59.999 最终成为 SQL Server 中的第二天。我从来没有遇到过 Oracle、Informix 或 MySQL 的问题,但其他数据库的精度可能也较低。您可以通过使用 Hibernate 自定义类型来解决它。当您写出日期值时,您必须四舍五入到比基础数据库精度更低的精度。在 Hibernate 文档中搜索 UserType,您将更改 nullSafeSet 方法以进行舍入。

    【讨论】:

    • 我也用MySql。这就是发生此问题的地方。嗯……奇怪。也许我必须设置一些option 才能允许这种精度?!
    【解决方案4】:

    显然,您的目标 RDBMS 上的 TIMESTAMP 类型(您在使用什么,顺便说一句?)不存储毫秒。尝试找到另一种可以执行此操作的原生类型,或者将您的时间映射到其他内容上,例如 long = ms-since-epoch。

    【讨论】:

    • 我使用 MySql 数据库。你指的另一种原生类型是什么?
    • 有些数据库有多种日期/时间数据类型。根据文档,MySQL中没有高精度的日期数据类型:(您唯一简单的选择是将日期时间映射为以毫秒为单位的时间到长。如果您创建自定义类型,甚至转换也是自动的。
    猜你喜欢
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多