JPA / HibernateおよびSQL Server DBを使用してJavaプロジェクトを開発しています。
日付フィールドが int として格納され、datetime が float として格納されている既存のデータベースを取得しました。
ドメインクラスで Calendar 型への透過的な変換を実装する方法を知っている人はいますか?
ゲッターとセッターで日付を計算する必要がありますか、それとももっと良い方法がありますか?
ありがとうございました!マルコ
JPA / HibernateおよびSQL Server DBを使用してJavaプロジェクトを開発しています。
日付フィールドが int として格納され、datetime が float として格納されている既存のデータベースを取得しました。
ドメインクラスで Calendar 型への透過的な変換を実装する方法を知っている人はいますか?
ゲッターとセッターで日付を計算する必要がありますか、それとももっと良い方法がありますか?
ありがとうございました!マルコ
これが私の解決策です!誰かに役立つことを願っています!
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()
};
}
}
私はそれを次のようにします:
UserType
インターフェイスを実装します。nullSafeGet()
実装では、この文字列をJoda DateTimeに変換するか、形式が「yyyyMMdd」Java.util.Date
のクラスを使用します。SimpleDateFormat
float
として読み取ります。実装では、この文字列もJoda Datetimeに変換するか、「yyyyMMdd.HHmmss」という形式のクラスを使用します。String
float
nullSafeGet()
java.util.Date
SimpleDateFormat
nullSafeSet()
同じものを使用してデータをフォーマットバックします。SimpleDateFormat
お役に立てれば。