web-dev-qa-db-de.com

JPA-Unterstützung für die neue Datums- und Uhrzeit-API von Java 8

Ich verwende Java 8 für mein neues Projekt.

Ich versuche, die neue Datums- und Uhrzeit-API in Java 8 zu verwenden. Ich weiß jedoch nicht, ob JPA 2.1 diese neue Datums- und Uhrzeit-API vollständig unterstützt.

Teilen Sie bitte Ihre Erfahrungen/Ansichten mit der Unterstützung von JPA für neue Datums- und Zeit-API in Java 8 mit.

Kann ich neue Datums- und Uhrzeit-API in Java 8 sicher mit JPA 2.1 verwenden?

UPDATE:

Ich verwende Hibernate (4.3.5.Final) als JPA-Implementierung.

53
TheKojuEffect

JPA 2.1 ist eine Spezifikation, die vor Java 1.8 herausgegeben wurde, daher ist keine Unterstützung dafür erforderlich. Offensichtlich unterstützen einige Implementierungen einige Java 1.8-Funktionen. Einige haben Probleme mit dem Java 1.8-Bytecode (z. B. EclipseLink). Ich weiß, dass DataNucleus Java.time und Java 1.8 unterstützt, da ich das hier benutze. Sie müssen Ihre Implementierung auf den Support-Level überprüfen.

Es wurde angefordert, dass JPA 2.2 die Java.time-Typen unterstützt. Weitere Informationen finden Sie in dieser Ausgabe https://Java.net/jira/browse/JPA_SPEC-63

19
Neil Stockton

Für Hibernate 5.X einfach hinzufügen

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-Java8</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

und 

@NotNull
@Column(name = "date_time", nullable = false)
protected LocalDateTime dateTime;

funktioniert ohne zusätzlichen Aufwand . Siehe https://hibernate.atlassian.net/browse/HHH-8844

AKTUALISIEREN:

Schauen Sie sich bitte Jeff Morins Kommentar an: Seit Hibernate 5.2.x reicht es aus

 <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-core</artifactId>
     <version>5.2.1.Final</version>
 </dependency>
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-...</artifactId>
     <version>4.3.1.RELEASE</version>
 </dependency>

Siehe https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2 und Integrieren Sie Hibernate 5.2 mit Spring Framework 4.x

70
GKislin

JPA 2.2 unterstützt Java.time

JPA 2.2 unterstützt jetzt LocalDate, LocalTime, LocalDateTime, OffsetTime und OffsetDateTime.

<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>javax.persistence-api</artifactId>
  <version>2.2</version>
</dependency>

Für die Implementierung von JPA 2.2 können Hibernate 5.2 oder EclipseLink 2.7 verwendet werden.

Der Ruhezustand 5 unterstützt mehr Java-Typen als JPA 2.2 wie Duration, Instant und ZonedDateTime.

Mehr Info: 

10
TheKojuEffect

Ich verwende Java 8, EclipseLink (JPA 2.1), PostgreSQL 9.3 und PostgreSQL Driver -Postgresql-9.2-1002.jdbc4.jar in meinem Projekt, und ich kann LocalDateTime-Variablen aus der neuen API ohne Probleme verwenden, aber den Datentyp der Spalte Da es sich in der Datenbank um Bytea handelt, können Sie es nur von einer Java-Anwendung lesen, soweit ich weiß. Sie können AttributeConverter verwenden, um die neuen Klassen in Java.sql.Date .__ zu konvertieren. Ich finde diesen Code von Java.net .

@Converter(autoApply = true)
public class LocalDatePersistenceConverter implements
AttributeConverter {
@Override
public Java.sql.Date convertToDatabaseColumn(LocalDate entityValue) {
    return Java.sql.Date.valueOf(entityValue);
}

@Override
public LocalDate convertToEntityAttribute(Java.sql.Date databaseValue) {
    return databaseValue.toLocalDate();
}
9
Ismael_Diaz

org.jadira.usertype kann verwendet werden, um die JSR 310-API für Datum und Uhrzeit zu persistieren.

Schauen Sie sich dieses Beispielprojekt an. 

Aus Beispielprojekt,

@MappedSuperclass
public class AbstractEntity {

    @Id @GeneratedValue Long id;

    @CreatedDate//
    @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
    ZonedDateTime createdDate;

    @LastModifiedDate//
    @Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
    ZonedDateTime modifiedDate;
}
8
TheKojuEffect

Ich weiß, dass dies eine alte Frage ist, aber ich dachte an eine alternative Lösung, die hilfreich sein könnte.

Anstatt zu versuchen, die neuen Java.time. * - Klassen einem vorhandenen Datenbanktyp zuzuordnen, können Sie @Transient nutzen:

@Entity
public class Person {
    private Long id;        
    private Timestamp createdTimestamp;

    @Id
    @GeneratedValue
    public Long getId() { return id; }

    private Timestamp getCreatedTimestamp() {
        return createdTime;
    }

    private void setCreatedTimestamp(final Timestamp ts) {
        this.createdTimestamp = ts;
    }

    @Transient
    public LocalDateTime getCreatedDateTime() {
        return createdTime.getLocalDateTime();
    }

    public void setCreatedDateTime(final LocalDateTime dt) {
        this.createdTime = Timestamp.valueOf(dt);
    }
}

Sie arbeiten mit den öffentlichen Getter/Setter-Methoden, die die neuen Java 8-Datums-/Zeitklassen verwenden, aber hinter den Kulissen arbeiten die Getter/Setter mit den älteren Datums-/Zeitklassen. Wenn Sie die Entität beibehalten, wird die alte Datums-/Uhrzeit-Eigenschaft beibehalten, nicht jedoch die neue Java 8-Eigenschaft, da sie mit @Transient kommentiert wird.

3
Jin Kim

Für den TypTIMESTAMPkönnen Sie diesen Konverter verwenden:

@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {

    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime datetime) {
        return datetime == null ? null : Timestamp.valueOf(datetime);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp timestamp) {
        return timestamp == null ? null : timestamp.toLocalDateTime();
    }

}

Für den TypDATEkönnen Sie diesen Konverter verwenden:

@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {

    @Override
    public Date convertToDatabaseColumn(LocalDate date) {
        return date == null ? null : Date.valueOf(date);
    }

    @Override
    public LocalDate convertToEntityAttribute(Date date) {
        return date == null ? null : date.toLocalDate();
    }

}

Für den TypTIMEkönnen Sie diesen Konverter verwenden:

@Converter(autoApply = true)
public class LocalTimeAttributeConverter implements AttributeConverter<LocalTime, Time> {

    @Override
    public Time convertToDatabaseColumn(LocalTime time) {
        return time == null ? null : Time.valueOf(time);
    }

    @Override
    public LocalTime convertToEntityAttribute(Time time) {
        return time == null ? null : time.toLocalTime();
    }

}
1
Paco

Es gibt viele Vorgehensweisen, die auch von Ihrer Rahmenarbeit abhängig sind: Wenn Ihre Rahmenarbeit auf dem Feldumwandler einen solchen Frühling hat, tun Sie Folgendes:

@DateTimeFormat(pattern = "dd.MM.yyyy - HH:mm")
private Long createdDate;

hier verwende ich das ältere Epoch-Format https://www.epochconverter.com/ Epoch ist sehr flexibel und akzeptiert das Format

2- Die andere Möglichkeit ist die Verwendung von jpa @PostLoad @PreUpdate @PrePersist

@PostLoad
      public void convert() {
        this.jva8Date= LocalDate.now().plusDays(1);
      }

oder verwenden Sie temporär ein solches 

@Transient
public LocalDateTime getCreatedDateTime() {
    return createdTime.getLocalDateTime();
}
0
Ali.Mojtehedy