2012-08-28 2 views
2

Я разрабатываю проект Java с JPA/Hibernate и SQL Server DB.Преобразование float/int в календарь в jpa hibernate SQL Server

Я получил существующий db, где поля даты хранятся как int и datetime как float.

Кто-нибудь знает, как я могу реализовать прозрачное преобразование в тип Календаря в моем классе домена?

Я должен рассчитать дату в геттере и сеттере, или есть лучший способ?

Спасибо! Marco

+0

что делать целые числа означают? Это 1100 11 утра или это 1100 секунд после 1970 года или 1100 мс после 1970 года. Подробнее см. – RNJ

+0

. Вы имеете в виду, что у вас есть два разных столбца, которые представляют дату и время, и они должны быть объединены в один класс 'Date' в объекте домена? Не могли бы вы привести пример того, как хранятся дата и время? – Thomas

+0

В Sql Сервер, выполняющий: выбрать cast (0 в качестве даты) -> 1900-01-01 00: 00: 00.000 выбрать cast (41148 as datetime) -> 2012-08-29 00: 00: 00.000 – gipinani

ответ

1

Я хотел бы сделать это следующим образом:

  1. Два класса, MyDate & MyDateTime каждый реализует интерфейс Hibernate UserType.
  2. MyDate прочитает дату целого в виде строки, предполагая, что число имеет формат 20120828. В nullSafeGet() реализации, она будет преобразовать эту строку в Joda DateTime или Java.util.Date использованием SimpleDateFormat класса с форматом, как «YYyyMmDd».
  3. MyDateTime будет читать float как String, предполагая, что float имеет формат 20120828.190800. В реализации nullSafeGet() он также преобразует эту строку в Jod Datetime или java.util.Date с использованием класса SimpleDateFormat с форматом «yyyyMMdd.HHmmss».
  4. nullSafeSet() будет отформатировать данные, используя те же SimpleDateFormat в соответствующих классах.

Надеюсь, это поможет.

2

Вот мое решение! Надежда полезна для кого-то!

Как было предложено Vikdor я реализовал интерфейс UserType:

public class MyDate implements UserType{ 

    private final static int SECONDS_IN_A_DAY = 86400; 

    @Override 
    public Object assemble(Serializable cached, Object owner) throws HibernateException { 
     return cached; 
    } 

    @Override 
    public Object deepCopy(Object value) throws HibernateException { 
     if (value == null) 
      return null; 

     return value; 
    } 

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

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

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

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

    @Override 
    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { 
     assert names.length == 1; 

     final String value = (String) StringType.INSTANCE.get(resultSet, names[0]); 
     if (value == null) return null;  
     try{ 
     final String daysValue = value.substring(0, value.indexOf(".")); 
      final String secondsValue = value.substring(value.indexOf(".")); 

      final Calendar calendar = Calendar.getInstance(); 
      calendar.set(Calendar.YEAR, 1900); 
      calendar.setTime(DateUtils.truncate(calendar, Calendar.YEAR).getTime()); 

      calendar.add(Calendar.DATE, Integer.valueOf(daysValue)); 
      calendar.add(Calendar.SECOND, (int)(SECONDS_IN_A_DAY * Float.valueOf(secondsValue))); 
      return calendar; 
     }catch(Exception e){ 
      throw new HibernateException("Cannot convert DB value " +value); 
     } 
    } 

    @Override 
    /** 
    * Convert from date to float 
    */ 
    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {  
     final Calendar currentDate = (Calendar) value; 
     final Calendar zeroDate = Calendar.getInstance(); 

     zeroDate.set(Calendar.YEAR, 1900); 
     zeroDate.setTime(DateUtils.truncate(zeroDate, Calendar.YEAR).getTime()); 

     final Days days = Days.daysBetween(new DateTime(zeroDate), new DateTime(currentDate)); 

     final Seconds seconds = Seconds.secondsBetween(new DateTime(DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH).getTime()), new DateTime(currentDate)); 
     float finalValue = days.getDays() + ((float)seconds.getSeconds()/SECONDS_IN_A_DAY); 

     preparedStatement.setFloat(index, finalValue);  
    } 

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

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

    @Override 
    public int[] sqlTypes() { 
     return new int[]{ 
       FloatType.INSTANCE.sqlType() 
     }; 
    } 

} 
Смежные вопросы