2013-07-16 2 views
1

У меня есть Calendar поле в моей сущностиHibernate - Mapping java.util.Calendar к MySQL BIGINT

@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 в моем объекте?

+0

Если вы используете более новую версию MySQL (5.6.4+), вы можете получить до микросекундной точности: http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds. html – Muel

+0

@Muel Любая идея, как сказать Hibernate использовать эту точность? –

+0

Hibernate ничего не нужно рассказывать. Это должно быть так же просто, как изменить существующий столбец базы данных, так что теперь это 'DATETIME (3)' вместо 'DATETIME (0)'. Все остальное должно работать. – Muel

ответ

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; 
    } 
} 

И мой Entity тогда имеет

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

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

    ... 
} 

Hibernate бог проклятая магическая.

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; 
+0

Joda 'DateTime' может иметь миллисекундную точность (так же как и« Календарь »), но моя версия MySQL ограничивает время до нескольких секунд. Записывает ли 'PersistentDateTime' поле' datetime'/'timestamp' или поле BIGINT? –

+0

Какую версию MySQL вы используете? Взгляните на комментарий @ Muel –

+0

Я на 5.5 или что-то в этом роде. Даже если бы я был на 5.6.4+, мне все равно пришлось бы установить его, но я разрешаю Hibernate генерировать схему так, как я могу заставить его использовать 'DATETIME (3)' например? –