2

JPA / HibernateおよびSQL Server DBを使用してJavaプロジェクトを開発しています。

日付フィールドが int として格納され、datetime が float として格納されている既存のデータベースを取得しました。

ドメインクラスで Calendar 型への透過的な変換を実装する方法を知っている人はいますか?

ゲッターとセッターで日付を計算する必要がありますか、それとももっと良い方法がありますか?

ありがとうございました!マルコ

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の2つのクラスは、それぞれHibernateUserTypeインターフェイスを実装します。
  2. MyDateは、整数の形式が20120828であると想定して、整数の日付を文字列として読み取ります。nullSafeGet()実装では、この文字列をJoda DateTimeに変換するか、形式が「yyyyMMdd」Java.util.Dateのクラスを使用します。SimpleDateFormat
  3. MyDateTimeは、が20120828.190800の形式であると想定して、floatとして読み取ります。実装では、この文字列もJoda Datetimeに変換するか、「yyyyMMdd.HHmmss」という形式のクラスを使用します。StringfloatnullSafeGet()java.util.DateSimpleDateFormat
  4. は、それぞれのクラスでnullSafeSet()同じものを使用してデータをフォーマットバックします。SimpleDateFormat

お役に立てれば。

于 2012-08-28T13:39:46.340 に答える