Java 8の日付/時刻型のJPA 2.2サポート

1. 概要

JPA 2.2バージョンでは、https://www.baeldung.com/java-8-date-time-intro [Java 8 _Date_ and _Time_ API]のサポートが正式に導入されました。 その前に、独自のソリューションに依存するか、JPA Converter APIを使用する必要がありました。
このチュートリアルでは、さまざまなJava 8の_Date_および_Time_タイプをマップする方法を示します*。 特に、オフセット情報を考慮するものに焦点を当てます。

2. Mavenの依存関係

開始する前に、JPA 2.2 APIをプロジェクトクラスパスに含める必要があります。 Mavenベースのプロジェクトでは、dependency_pom.xml_ファイルにその依存関係を簡単に追加できます。
<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>javax.persistence-api</artifactId>
    <version>2.2</version>
</dependency>
さらに、プロジェクトを実行するには、JPA実装と作業するデータベースのJDBCドライバーが必要です。 このチュートリアルでは、EclipseLinkとPostgreSQLデータベースを使用します。
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.7.4-RC1</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.5</version>
    <scope>runtime</scope>
    <type>bundle</type>
</dependency>
https://search.maven.org/search?q=g:javax.persistence%20AND%20a:javax.persistence-apiの最新バージョンをお気軽にご確認ください
もちろん、他のデータベースまたはHibernateなどのJPA実装を使用できます。

3. TimeZoneのサポート

任意のデータベースで作業できますが、最初に、JDBC 4.2は以下に基づいているため、これらの標準SQLタイプのサポートを確認する必要があります。
  • TIMESTAMP(n)WITH TIME ZONE

  • TIMESTAMP(n)時間帯なし

  • TIME(n)WITH TIME ZONE

  • TIME(n)時間帯なし

    ここで、_n_は秒の小数部の精度であり、0〜9桁です。 _WITHOUT TIME ZONE_はオプションであり、省略できます。 _WITH TIME ZONE_が指定されている場合、タイムゾーン名またはUTCへのオフセットが必要です。
    次の2つの形式のいずれかでタイムゾーンを表すことができます。
  • タイムゾーン名

  • UTCからのオフセットまたはUTCの文字Z

    この例では、SQLタイプ_TIME WITH TIME ZONE_を完全にサポートしているため、PostgreSQLデータベースを選択しました。
    他のデータベースはこれらのタイプをサポートしていない可能性があることに注意してください。

*4. Java 8 *より前の日付タイプのマッピング

Java 8より前は、通常、汎用SQL型_TIME、DATE_、および_TIMESTAMP_、を_java.sql。* _ classes _java.sql.Time_、_java.sql.Date、_および_java.sql.Timestampのいずれかにマップする必要がありました。 _それぞれ、または_java.util_型_java.util.Date_および_java.util.Calendar_に。
最初に、_java.sql_型の使用方法を見てみましょう。 ここでは、単に_ @ Entity_クラスの一部として_java.sql_型の属性を定義しています。
@Entity
public class JPA22DateTimeEntity {

    private java.sql.Time sqlTime;
    private java.sql.Date sqlDate;
    private java.sql.Timestamp sqlTimestamp;

    // ...
}
  • _java.sql_型は追加のマッピングなしで他の型と同様に機能しますが、_java.util_型は対応する一時的な型を指定する必要があります。*

    これは、@ _ TemporalType_ enumerationを使用して、対応するJDBCタイプを指定できる_value_属性を持つ_ @ Temporal_アノテーションによって行われます。
@Temporal(TemporalType.TIME)
private java.util.Date utilTime;

@Temporal(TemporalType.DATE)
private java.util.Date utilDate;

@Temporal(TemporalType.TIMESTAMP)
private java.util.Date utilTimestamp;
Hibernateを実装として使用している場合、_Calendar_から_TIME_へのマッピングはサポートされないことに注意してください。
同様に、_Calendar_クラスを使用できます。
@Temporal(TemporalType.TIME)
private Calendar calendarTime;

@Temporal(TemporalType.DATE)
private Calendar calendarDate;

@Temporal(TemporalType.TIMESTAMP)
private Calendar calendarTimestamp;
これらのタイプはいずれも、タイムゾーンまたはオフセットをサポートしていません。 これらの情報を処理するために、従来はUTC時間を保存する必要がありました。

5. Java 8の日付タイプのマッピング

Java 8は_java.time_パッケージを導入し、JDBC 4.2 APIは追加のSQL型_TIMESTAMP WITH TIME ZONE_および_TIME WITH TIME ZONE_のサポートを追加しました。
  • JDBCタイプ_TIME、DATE、および_TIMESTAMP_を_java.time_タイプにマップできるようになりました*– _LocalTime、 LocalDate、および_LocalDateTime_:

@Column(name = "local_time", columnDefinition = "TIME")
private LocalTime localTime;

@Column(name = "local_date", columnDefinition = "DATE")
private LocalDate localDate;

@Column(name = "local_date_time", columnDefinition = "TIMESTAMP")
private LocalDateTime localDateTime;
さらに、_OffsetTime_および_OffsetDateTime_クラスを介してUTCへのローカルタイムゾーンのオフセットをサポートしています。
@Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE")
private OffsetTime offsetTime;

@Column(name = "offset_date_time", columnDefinition = "TIMESTAMP WITH TIME ZONE")
private OffsetDateTime offsetDateTime;
対応するマップされた列タイプは、_TIME WITH TIME ZONE_および_TIMESTAMP WITH TIME ZONE_でなければなりません。 残念ながら、すべてのデータベースがこれら2つのタイプをサポートしているわけではありません。
ご覧のとおり、JPAはこれらの5つのクラスを基本型としてサポートしており、日付と時刻の情報を区別するために追加情報は必要ありません。
エンティティクラスの新しいインスタンスを保存した後、データが正しく挿入されたことを確認できます。
link:/uploads/date_time-100x8.png%20100w []

6. 結論

Java 8およびJPA 2.2より前は、開発者は通常、日付/時刻型を永続化する前にUTCに変換する必要がありました。 JPA 2.2は、UTCへのオフセットをサポートし、タイムゾーンのJDBC 4.2サポートを活用することにより、この機能をすぐにサポートするようになりました。
これらのサンプルの完全なソースコードは、https://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa [Github上]にあります。