2

我正在使用 JPA / Hibernate 和 SQL Server DB 开发一个 Java 项目。

我有一个现有的数据库,其中日期字段存储为 int,日期时间存储为浮点数。

有谁知道如何在我的域类中实现对日历类型的透明转换?

我必须在 getter 和 setter 中计算日期还是有更好的方法?

谢谢!马可

4

2 回答 2

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

}
于 2012-08-29T10:03:22.300 回答
1

我会这样做:

  1. 两个类,MyDate 和 MyDateTime,每个都实现了 HibernateUserType接口。
  2. MyDate 会将整数日期读取为字符串,假设整数格式为 20120828。在nullSafeGet()实现中,它将将此字符串转换为 Joda DateTime 或Java.util.Date使用SimpleDateFormat格式为“yyyyMMdd”的类。
  3. MyDateTime 将读取floatas String,假设float格式为 20120828.190800。在nullSafeGet()实现中,它也会将此字符串转换为 Joda Datetime 或java.util.Date使用SimpleDateFormat格式为“yyyyMMdd.HHmmss”的类。
  4. 将在各自的类中nullSafeSet()使用相同的格式重新格式化数据。SimpleDateFormat

希望这可以帮助。

于 2012-08-28T13:39:46.340 回答