Convierta float/int a Calendar en jpa hibernate SQL Server

I'm developing a Java project with JPA / Hibernate and SQL Server DB.

I got an existent db where date fields are stored as int and datetime as float.

Does anyone know how can I implement a transparent conversion to a Calendar type in my domain class?

I must calculate the date in getter and setter or there's a better way?

¡Gracias! Marco

preguntado el 28 de agosto de 12 a las 14:08

what do the integers mean? Is 1100 11am or is that 1100 seconds after 1970 or 1100 ms after 1970. more infor please -

Do you mean you have two different columns that represent date and time and those should be merged to a single Date class in the domain object? Could you give an example of how the date and time are stored? -

In Sql Server executing: select cast(0 as datetime) -> 1900-01-01 00:00:00.000 select cast(41148 as datetime) -> 2012-08-29 00:00:00.000 -

2 Respuestas

Here is my solution! Hope is useful for someone!

As suggested by Vikdor I've implemented UserType interface:

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

}

Respondido 29 ago 12, 11:08

Lo haría de la siguiente manera:

  1. Two classes, MyDate & MyDateTime each implementing the Hibernate UserType de la interfaz del.
  2. MyDate will read the integer date as String, assuming the integer is of the format 20120828. In the nullSafeGet() implementation, it will convert this string to a Joda DateTime or Java.util.Date usando el SimpleDateFormat class with format as "yyyyMMdd".
  3. MyDateTime will read the float as String, asumiendo el float is of the format 20120828.190800. In the nullSafeGet() implementation, it too will convert this string to a Joda Datetime or java.util.Date usando el SimpleDateFormat class with format as "yyyyMMdd.HHmmss".
  4. Programas de nullSafeSet() will format back the data using the same SimpleDateFormat in the respective classes.

Espero que esto ayude.

Respondido el 12 de diciembre de 16 a las 08:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.