Înlocuiţi adnotarea Temporal cu o adnotare Converter pentru unele atribute java.sql

OpenJPA persistă câmpurile atributelor de tipul java.sql.Date, java.sql.Time sau java.sql.Timestamp care au o adnotare javax.persistence.Temporal, în care EclipseLink aruncă o excepţie.

Pentru unele combinaţii de adnotare javax.persistence.Temporal şi atribute java.sql.Date, java.sql.Time şi java.sql.Timestamp, trebuie să adăugaţi codul convertorului pentru ca EclipseLink să fie compatibil cu tabelele care au fost create de OpenJPA.

Această regulă scanează pentru trei combinaţii adnotare-atribut unde o clasă convertor este necesară pentru a transforma datele între baza de date şi entitate:

Pentru cazurile în care nu este necesară o conversie şi adnotarea Temporal nu poate fi înlăturată, vedeţi regula Înlăturare adnotare Temporal pentru unele atribute java.sql.

@Temporal(TemporalType.TIMESTAMP) pe un atribut java.sql.Date

În acest caz, regula semnalează adnotarea Temporal(TemporalType.TIMESTAMP).

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

Pentru a rezolva această problemă, creaţi o clasă de utilitate convertor comună care poate fi folosită pentru toate atributele care au nevoie de acest convertor:

  1. Creaţi o clasă Converter care converteşte o dată la o amprentă de timp, ca în exemplul următor.
    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. Adăugaţi clasa convertorului la definiţia persistenţă unitate.
  3. Înlocuiţi adnotarea Temporal(TemporalType.TIMESTAMP) din atributul java.sql.Date cu o adnotare Convert care are atributul converter setat la clasa convertorului nou.

    Următorul exemplu arată adnotarea Temporal(TemporalType.TIMESTAMP) originală:

    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
    clasă publică TemporalEntityOJ {
        @Id
        int privat id;
        @Temporal(TemporalType.TIMESTAMP)
        privat java.sql.Date sqlDateTIMESTAMP;
    }
    

    Următorul exemplu arată noua adnotare 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
    clasă publică TemporalEntityOJ {
        @Id
        int privat id;
        @Convert(converter=DateTimestampConverter.class)
        privat java.sql.Date sqlDateTIMESTAMP;
    }
    

@Temporal(TemporalType.DATE) pe un atribut java.sql.Timestamp

În acest caz, regula semnalează adnotarea Temporal(TemporalType.DATE).

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

Pentru a rezolva această problemă, creaţi o clasă de utilitate convertor comună care poate fi folosită pentru toate atributele care au nevoie de acest convertor:

  1. Creaţi o clasă Converter care converteşte o amprentă de timp la o dată, ca în exemplul următor.
    import java.sql.Date;
    import java.sql.Timestamp;
    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter
    clasă publică TimestampDateAnnConverter implements AttributeConverter<Timestamp, Date>{
        @Override
        public Date convertToDatabaseColumn(Timestamp ts) {
            retur nou Date(ts.getTime());
        }
    
        @Override
        public Timestamp convertToEntityAttribute(Date date) {
            retur nou Timestamp(date.getTime());
        }
    }
    
  2. Adăugaţi clasa convertorului la definiţia persistenţă unitate.
  3. Înlocuiţi adnotarea Temporal(TemporalType.DATE) din atributul java.sql.Timestamp cu o adnotare Convert care are atributul converter setat la clasa convertorului nou.

    Următorul exemplu arată adnotarea Temporal(TemporalType.DATE) originală:

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

    Următorul exemplu arată noua adnotare 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
    clasă publică TemporalEntityOJ {
        @Id
        int privat id;
        @Convert(converter=TimestampDateAnnConverter.class)
        privat java.sql.Timestamp sqlTimestampDate;
    }
    

@Temporal(TemporalType.TIME) pe un atribut java.sql.Timestamp

În acest caz, regula semnalează adnotarea Temporal(TemporalType.TIME).

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

Pentru a rezolva această problemă, creaţi o clasă de utilitate convertor comună care poate fi folosită pentru toate atributele care au nevoie de acest convertor:

  1. Creaţi o clasă Converter care converteşte o amprentă de timp la un timp, ca în exemplul următor.
    import java.sql.Time;
    import java.sql.Timestamp;
    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter
    clasă publică TimestampTimeAnnConverter Instrumente AttributeConverter<Timestamp, Time>{
        @Override
        Timp public convertToDatabaseColumn(Timestamp ts) {
            retur nou Time(ts.getTime());
        }
    
        @Override
        public Timestamp convertToEntityAttribute(Time time) {
            retur nou Timestamp(time.getTime());
        }
    }
    
  2. Adăugaţi clasa convertorului la definiţia persistenţă unitate.
  3. Înlocuiţi adnotarea Temporal(TemporalType.TIME) din atributul java.sql.Timestamp cu o adnotare Convert care are atributul converter setat la clasa convertorului nou.

    Următorul exemplu arată adnotarea Temporal(TemporalType.TIME) originală:

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

    Următorul exemplu arată noua adnotare 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
    clasă publică TemporalEntityOJ {
        @Id
        int privat id;
        @Convert(converter=TimestampTimeAnnConverter.class)
        privat java.sql.Timestamp sqlTimestampTime;
    }
    

Pentru informaţii despre această problemă şi alte probleme legate de migrarea OpenJPA la EclipseLink, vedeţi ghidul OpenJPA to EclipseLink JPA Migration: Mappings.