【问题标题】:Convert float/int to Calendar in jpa hibernate SQL Server在 jpa hibernate SQL Server 中将浮点数/整数转换为日历
【发布时间】:2012-08-23 00:32:33
【问题描述】:

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

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

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

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

谢谢! 马可

【问题讨论】:

  • 整数是什么意思?是 1100 上午 11 点,还是 1970 年之后的 1100 秒或 1970 年之后的 1100 毫秒。请提供更多信息
  • 您的意思是您有两个不同的列代表日期和时间,并且应该将它们合并到域对象中的单个 Date 类中吗?能否举例说明日期和时间是如何存储的?
  • 在 Sql Server 中执行:select cast(0 as datetime) -> 1900-01-01 00:00:00.000 select cast(41148 as datetime) -> 2012-08-29 00:00: 00.000

标签: java sql-server hibernate jpa


【解决方案1】:

这是我的解决方案!希望对某人有用!

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

}

【讨论】:

    【解决方案2】:

    我会这样做:

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

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多