web-dev-qa-db-ja.com

Java 8つの新しい日時APIのJPAサポート

私はJava 8を新しいプロジェクトに使用しています。

Java 8で新しい日時APIを使用しようとしていますが、JPA 2.1は、この新しい日時APIを完全にサポートするかどうかを決定します。

Java 8.のJPAの新しい日時APIのサポートでの経験/意見を共有してください。

Java 8で新しい日付と時刻APIを使用できますか?

更新:

JPA実装としてHibernate(4.3.5.Final)を使用しています。

55
TheKojuEffect

JPA 2.1はJava 1.8より前に出された仕様であるため、サポートを義務付けていません。明らかに、いくつかの実装はいくつかのJava 1.8機能をサポートするかもしれません。 Java 1.8バイトコード(EclipseLinkなど)に問題がある人もいます。 DataNucleusがJava.timeとJava 1.8をサポートしているのは、それが私が使用しているものだからです。実装のサポートレベルを確認する必要があります。

JPA 2.2がJava.time型をサポートすることが要求されています。この問題を参照してください https://Java.net/jira/browse/JPA_SPEC-6

19
Neil Stockton

Hibernate 5.Xの場合は、追加するだけです

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

そして

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

追加の努力なしで動作します。 https://hibernate.atlassian.net/browse/HHH-8844 を参照してください

更新:

Jeff Morinのコメントをご覧ください:Hibernate 5.2.x以降で十分です

 <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>

https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2 および Spring Framework 4.xでHibernate 5.2を統合 を参照してください

71
GKislin

JPA 2.2はJava.timeをサポートします

JPA 2.2LocalDateLocalTimeLocalDateTimeOffsetTimeをサポートするようになりました。 OffsetDateTime

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

JPA 2.2実装の場合、Hibernate 5.2またはEclipseLink 2.7を使用できます。

Hibernate 5は、DurationInstantZonedDateTimeなど、JPA 2.2よりも多くのJavaタイプをサポートしています。

詳細:

11
TheKojuEffect

org.jadira.usertype を使用して、JSR 310 Date and Time APIを永続化できます。

これを確認してください サンプルプロジェクト

サンプルプロジェクトから、

@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;
}
9
TheKojuEffect

私はJava 8、EclipseLink(JPA 2.1)、PostgreSQL 9.3およびPostgreSQL Driver -Postgresql-9.2-1002.jdbc4.jarをプロジェクトで使用しています。新しいAPIのLocalDateTime変数を使用できます問題ありませんが、データベースの列のデータ型はbyteaであるため、これを読み取ることができるのは、Java私の知る限りです。AttributeConverterを使用して新しいクラスをJavaに変換できます。 .sql.Date 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

私はこれが古い質問であることを知っていますが、役に立つかもしれない別の解決策を考えました。

新しいJava.time。*クラスを既存のデータベースタイプにマップする代わりに、@ Transientを活用できます。

@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);
    }
}

新しいJava 8日付/時刻クラスを使用するgetter/setterパブリックメソッドを使用しますが、舞台裏では、ゲッター/セッターは従来の日付/時刻クラスを使用します。エンティティの場合、レガシーの日付/時刻プロパティは永続化されますが、@ Transientアノテーションが付けられているため、新しいJava 8プロパティは永続化されません。

3
Jin Kim

タイプ[〜#〜] timestamp [〜#〜]の場合、このコンバーターを使用できます。

@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();
    }

}

タイプ[〜#〜] date [〜#〜]の場合、このコンバーターを使用できます。

@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();
    }

}

タイプ[〜#〜] time [〜#〜]の場合、このコンバーターを使用できます。

@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

行うには多くのアプローチがありますが、フレームワークにも依存します:フレームワークがフィールドコンバータにある場合、そのような春は次のようにします:1-

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

ここでは、古いEpoch形式を使用しています https://www.epochconverter.com/ Epochは非常に柔軟で受け入れられている形式です

2-他の方法は、jpa @PostLoad @PreUpdate @PrePersistを使用することです

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

または、tempなどを使用します

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