【问题标题】:Hibernate - Mapping java.util.Calendar to MySQL BIGINTHibernate - 将 java.util.Calendar 映射到 MySQL BIGINT
【发布时间】:2013-07-15 07:42:16
【问题描述】:

我的实体中有一个Calendar 字段

@Column(nullable = false)
private Calendar transmissionDate;

需要毫秒精度。照原样,Hibernate 生成一个模式,将此字段映射到一个

+-------------------+--------------+------+-----+---------+
| Field             | Type         | Null | Key | Default | 
+-------------------+--------------+------+-----+---------+
| transmission_date | datetime     | NO   |     | NULL    |
+-------------------+--------------+------+-----+---------+

在 MySQL 中。 The datetime type in MySQL discards everything after the second,所以我失去了精确度。我现在一直在使用的解决方案是

@Column(nullable = false)
private Long transmissionDate;

并在需要时从中生成日历实例。

这是一个巨大的麻烦,我想知道 Hibernate 是否有可以克服它的功能。 This question 展示了如何使用自定义类型,但是,在实现它时,Hibernate 仍然映射到 datetime 列类型。

如何在我的实体中仍然使用Calendar 类型的同时保持毫秒精度?

【问题讨论】:

  • 如果您使用的是更新版本的 MySQL (5.6.4+),您可以达到微秒级精度:dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
  • @Muel 知道如何告诉 Hibernate 使用这种精度吗?
  • Hibernate 不需要被告知任何事情。它应该像修改现有数据库列一样简单,现在它是DATETIME(3) 而不是DATETIME(0)。其他一切都应该正常工作。

标签: java mysql hibernate


【解决方案1】:

我使用自定义的UserType 让它工作,该Calendar 映射到BIGINT

public class CalendarType implements UserType {

    @Override
    public int[] sqlTypes() {
        return new int[] {Types.BIGINT};
    }

    @Override
    public Class<?> returnedClass() {
        return Calendar.class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return x.equals(y);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet resultSet, String[] names,SessionImplementor session, Object owner) throws HibernateException, SQLException {
        Long timeInMillis = resultSet.getLong(names[0]);
        if (timeInMillis == null) {
            return null;
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(timeInMillis);
            return calendar;
        }       
    }

    @Override
    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
        Calendar calendar = (Calendar) value;
        preparedStatement.setLong(index, calendar.getTimeInMillis());       
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        Calendar calendar = (Calendar) value;       
        return calendar.getTimeInMillis();
    }

    @Override
    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        Long timeInMillis = (Long) cached;

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timeInMillis);
        return calendar;
    }

    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

然后我的实体有

@TypeDef(name = "calendarType", typeClass = CalendarType.class)
@Entity
@Table
public class Entity {

    @Type(type = "calendarType")
    @Column(nullable = false)
    private Calendar transmissionDate;

    ...
}

Hibernate 真是太神奇了。

【讨论】:

    【解决方案2】:

    使用乔达DateTime。您可以使用org.joda.time.contrib.hibernate.PersistentDateTimemap it directly in Hibernate,它具有毫秒精度。

    @Column
    @Type(type="org.joda.time.contrib.hibernate.PersistentDateTime")
    private DateTime transmissionDate;
    

    【讨论】:

    • Joda DateTime 可能具有毫秒精度(Calendar 也是如此),但我的 MySQL 版本将时间限制为秒。 PersistentDateTime 是写入 datetime/timestamp 字段还是 BIGINT 字段?
    • 您使用的是哪个 MySQL 版本?看看@Muel 的评论
    • 我在 5.5 上。即使我在 5.6.4+ 上,我仍然需要设置它,但我让 Hibernate 生成架构,那么我如何强制它使用 DATETIME(3) 例如?
    猜你喜欢
    • 2015-02-10
    • 2011-11-14
    • 2023-03-29
    • 1970-01-01
    • 2012-04-06
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    相关资源
    最近更新 更多