一部の java.sql 属性の Temporal アノテーションを Converter アノテーションに置き換える

OpenJPA では、javax.persistence.Temporal アノテーションを持つ java.sql.Date 型、java.sql.Time 型、または java.sql.Timestamp 型の属性のフィールドは永続化されるのに対し、EclipseLink では例外がスローされます。

javax.persistence.Temporal アノテーションと java.sql.Datejava.sql.Time、および java.sql.Timestamp の各属性の一部の組み合わせでは、EclipseLink が OpenJPA で作成されたテーブルとの互換性を持つように、コンバーター・コードを追加する必要があります。

この規則は、データベースとエンティティー間でデータを変換するためにコンバーター・クラスが必要となる、アノテーションと属性の 3 つの組み合わせをスキャンします。

変換が不要で Temporal アノテーションを削除できる場合については、 一部の java.sql 属性の Temporal アノテーションを削除する規則を参照してください。

java.sql.Date 属性上の @Temporal(TemporalType.TIMESTAMP)

このケースでは、規則は Temporal(TemporalType.TIMESTAMP) アノテーションにフラグを立てます。

   @javax.persistence.Temporal(TemporalType.TIMESTAMP)
   private java.sql.Date date;

この問題を解決するには、このコンバーターを必要とするすべての属性に使用できる共通コンバーター・ユーティリティー・クラスを作成します。

  1. 以下の例のような、日付をタイム・スタンプに変換する Converter クラスを作成します。
    import java.sql.Date;
    import java.sql.Timestamp;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    
    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter
    public class DateTimestampConverter implements AttributeConverter<Date, Timestamp> {
        @Override
        public Timestamp convertToDatabaseColumn(Date date) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
            return new Timestamp(cal.getTime().getTime());
        }
    
        @Override
        public Date convertToEntityAttribute(Timestamp timestamp) {
            return new Date(timestamp.getTime());
        }
    }
    
  2. 永続ユニット定義にコンバーター・クラスを追加します。
  3. java.sql.Date 属性上の Temporal(TemporalType.TIMESTAMP) アノテーションを、新しいコンバーター・クラスに設定された converter 属性を持つ Convert アノテーションに置き換えます。

    以下の例は、変更前の Temporal(TemporalType.TIMESTAMP) アノテーションを示します。

    import javax.persistence.Convert;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Temporal(TemporalType.TIMESTAMP)
        private java.sql.Date sqlDateTIMESTAMP;
    }
    

    以下の例は、新しい Convert アノテーションを示します。

    import javax.persistence.Convert;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Convert(converter=DateTimestampConverter.class)
        private java.sql.Date sqlDateTIMESTAMP;
    }
    

java.sql.Timestamp 属性上の @Temporal(TemporalType.DATE)

このケースでは、規則は Temporal(TemporalType.DATE) アノテーションにフラグを立てます。

   @javax.persistence.Temporal(TemporalType.DATE)
   private java.sql.Timestamp timestamp;

この問題を解決するには、このコンバーターを必要とするすべての属性に使用できる共通コンバーター・ユーティリティー・クラスを作成します。

  1. 以下の例のような、タイム・スタンプを日付に変換する Converter クラスを作成します。
    import java.sql.Date;
    import java.sql.Timestamp;
    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter
    public class TimestampDateAnnConverter implements AttributeConverter<Timestamp, Date>{
        @Override
        public Date convertToDatabaseColumn(Timestamp ts) {
            return new Date(ts.getTime());
        }
    
        @Override
        public Timestamp convertToEntityAttribute(Date date) {
            return new Timestamp(date.getTime());
        }
    }
    
  2. 永続ユニット定義にコンバーター・クラスを追加します。
  3. java.sql.Timestamp 属性上の Temporal(TemporalType.DATE) アノテーションを、新しいコンバーター・クラスに設定された converter 属性を持つ Convert アノテーションに置き換えます。

    以下の例は、変更前の Temporal(TemporalType.DATE) アノテーションを示します。

    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Temporal(TemporalType.DATE)
        private java.sql.Timestamp sqlTimestampDate;
    }
    

    以下の例は、新しい Convert アノテーションを示します。

    import javax.persistence.Convert;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Convert(converter=TimestampDateAnnConverter.class)
        private java.sql.Timestamp sqlTimestampDate;
    }
    

java.sql.Timestamp 属性上の @Temporal(TemporalType.TIME)

このケースでは、規則は Temporal(TemporalType.TIME) アノテーションにフラグを立てます。

   @javax.persistence.Temporal(TemporalType.TIME)
   private java.sql.Timestamp timestamp;

この問題を解決するには、このコンバーターを必要とするすべての属性に使用できる共通コンバーター・ユーティリティー・クラスを作成します。

  1. 以下の例のような、タイム・スタンプを時刻に変換する Converter クラスを作成します。
    import java.sql.Time;
    import java.sql.Timestamp;
    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter
    public class TimestampTimeAnnConverter implements AttributeConverter<Timestamp, Time>{
        @Override
        public Time convertToDatabaseColumn(Timestamp ts) {
            return new Time(ts.getTime());
        }
    
        @Override
        public Timestamp convertToEntityAttribute(Time time) {
            return new Timestamp(time.getTime());
        }
    }
    
  2. 永続ユニット定義にコンバーター・クラスを追加します。
  3. java.sql.Timestamp 属性上の Temporal(TemporalType.TIME) アノテーションを、新しいコンバーター・クラスに設定された converter 属性を持つ Convert アノテーションに置き換えます。

    以下の例は、変更前の Temporal(TemporalType.TIME) アノテーションを示します。

    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Temporal(TemporalType.TIME)
        private java.sql.Timestamp sqlTimestampTime;
    }
    

    以下の例は、新しい Convert アノテーションを示します。

    import javax.persistence.Convert;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    @Entity
    public class TemporalEntityOJ {
        @Id
        private int id;
        @Convert(converter=TimestampTimeAnnConverter.class)
        private java.sql.Timestamp sqlTimestampTime;
    }
    

この問題や、OpenJPA から EclipseLink へのマイグレーションに関するその他の問題については、 OpenJPA to EclipseLink JPA Migration: Mappings ガイドを参照してください。