Hibernate - 将java.util.Calendar映射到MySQL BIGINT

时间:2013-07-16 22:40:47

标签: java mysql hibernate

我的实体中有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;

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

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

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

2 个答案:

答案 0 :(得分: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是该死的神奇。

答案 1 :(得分:0)

使用Joda DateTime。您可以map it directly in Hibernate使用org.joda.time.contrib.hibernate.PersistentDateTime类,它具有毫秒精度。

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