1前書き

この記事では、

java.sql



java.util

、および

java.time

パッケージのクラスを含め、Hibernateで時系列列の値をマップする方法を説明します。


2プロジェクト設定

時間型のマッピングを説明するために、H2データベースと最新版の

hibernate-core

ライブラリが必要になります。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.12.Final</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.194</version>
</dependency>

現在のバージョンの

hibernate-core

ライブラリについては、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.hibernate%22%20AND%20a%3A%にアクセスしてください。 22hibernate-core%22[Maven Central]リポジトリ。


3タイムゾーンの設定

  • 日付を扱うときは、JDBCドライバに特定のタイムゾーンを設定することをお勧めします。

この例では、セッションごとに設定します。

session = HibernateUtil.getSessionFactory().withOptions()
  .jdbcTimeZone(TimeZone.getTimeZone("UTC"))
  .openSession();

もう1つの方法は、セッションファクトリの構築に使用されるHibernateプロパティファイルで

hibernate.jdbc.time

zone__プロパティを設定することです。これにより、アプリケーション全体に対して1回タイムゾーンを指定できます。


4

java.sql

型のマッピング


java.sql

パッケージには、標準SQLで定義されている型と一致するJDBC型が含まれています。


  • Date



    DATE

    SQL型に対応します。これは日付のみです。

時間がない
**

Time



TIME

SQL型に対応します。これはその日の時刻です。

時、分、秒で指定
**

Timestamp

には、日付と時刻に関する情報が正確に含まれます

ナノ秒までで、

TIMESTAMP

SQL型に対応します

これらの型はSQLと一致しているので、それらのマッピングは比較的簡単です。

@ Basic

アノテーションまたは

@ Column

アノテーションを使用できます。

@Entity
public class TemporalValues {

    @Basic
    private java.sql.Date sqlDate;

    @Basic
    private java.sql.Time sqlTime;

    @Basic
    private java.sql.Timestamp sqlTimestamp;

}

その後、対応する値を次のように設定できます。

temporalValues.setSqlDate(java.sql.Date.valueOf("2017-11-15"));
temporalValues.setSqlTime(java.sql.Time.valueOf("15:30:14"));
temporalValues.setSqlTimestamp(
  java.sql.Timestamp.valueOf("2017-11-15 15:30:14.332"));

エンティティフィールドにjava.sql型を選択することが常に良い選択とは限らないことに注意してください。これらのクラスはJDBC固有であり、多くの非推奨機能が含まれています。


5マッピング

java.util.Date

Type


  • java.util.Date

    型には、ミリ秒の精度までの日付と時刻の両方の情報が含まれます。

これが、目的のSQL型を指定するための別の注釈が必要な理由です。

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

@Basic
@Temporal(TemporalType.TIME)
private java.util.Date utilTime;

@Basic
@Temporal(TemporalType.TIMESTAMP)
private java.util.Date utilTimestamp;


@ Temporal

アノテーションには

TemporalType型の単一パラメータ値があります。マッピングに使用する基礎となるSQL型に応じて、

DATE



TIME

、または

TIMESTAMP__のいずれかになります。

対応するフィールドを次のように設定します。

temporalValues.setUtilDate(
  new SimpleDateFormat("yyyy-MM-dd").parse("2017-11-15"));
temporalValues.setUtilTime(
  new SimpleDateFormat("HH:mm:ss").parse("15:30:14"));
temporalValues.setUtilTimestamp(
  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
    .parse("2017-11-15 15:30:14.332"));

これまで見てきたように、

java.util.Date

タイプ(ミリ秒の精度)は、タイムスタンプ値(ナノ秒の精度)を処理するのに十分なほど正確ではありません。

そのため、データベースからエンティティを取得すると、最初は

java.util.Date

を永続化していても、当然ながらこのフィールドに

java.sql.Timestamp

インスタンスが見つかります。

temporalValues = session.get(TemporalValues.class,
  temporalValues.getId());
assertThat(temporalValues.getUtilTimestamp())
  .isEqualTo(java.sql.Timestamp.valueOf("2017-11-15 15:30:14.332"));


Timestamp



Date

を拡張しているので、これは私たちのコードにとっては問題ないはずです。


6. マッピング

java.util.Calendar

タイプ


java.util.Date

と同様に、

java.util.Calendar

タイプは異なるSQLタイプにマップされる可能性があるため、

@ Temporal

を使用してそれらを指定する必要があります。

唯一の違いは、Hibernateが

Calendar

から

TIME

へのマッピングをサポートしていないことです。

@Basic
@Temporal(TemporalType.DATE)
private java.util.Calendar calendarDate;

@Basic
@Temporal(TemporalType.TIMESTAMP)
private java.util.Calendar calendarTimestamp;

フィールドの値を設定する方法は次のとおりです。

Calendar calendarDate = Calendar.getInstance(
  TimeZone.getTimeZone("UTC"));
calendarDate.set(Calendar.YEAR, 2017);
calendarDate.set(Calendar.MONTH, 10);
calendarDate.set(Calendar.DAY__OF__MONTH, 15);
temporalValues.setCalendarDate(calendarDate);


7.

java.time

型のマッピング

  • Java 8以降、新しいJava Date and Time APIが時間値を扱うために利用可能になりました** 。このAPIは、

    java.util.Date

    および

    java.util.Calendar

    クラスの多くの問題を解決します。


java.time

パッケージの型は、対応するSQL型に直接マッピングされています。そのため、

@ Temporal

アノテーションを明示的に指定する必要はありません。


  • LocalDate



    DATE

    にマップされます


  • LocalTime



    OffsetTime



    TIME

    にマップされます


  • Instant



    LocalDateTime



    OffsetDateTime

    、および

    ZonedDateTime

    は、


TIMESTAMP

にマッピング

これは、次のように、これらのフィールドに

@ Basic

(または

@ Column

)アノテーションでのみマークを付けることができることを意味します。

@Basic
private java.time.LocalDate localDate;

@Basic
private java.time.LocalTime localTime;

@Basic
private java.time.OffsetTime offsetTime;

@Basic
private java.time.Instant instant;

@Basic
private java.time.LocalDateTime localDateTime;

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;


java.time

パッケージ内のすべての一時クラスには、提供された

String

値を適切な形式で解析するための静的

parse()

メソッドがあります。それで、エンティティフィールドの値を設定する方法は次のとおりです。

temporalValues.setLocalDate(LocalDate.parse("2017-11-15"));

temporalValues.setLocalTime(LocalTime.parse("15:30:18"));
temporalValues.setOffsetTime(OffsetTime.parse("08:22:12+01:00"));

temporalValues.setInstant(Instant.parse("2017-11-15T08:22:12Z"));
temporalValues.setLocalDateTime(
  LocalDateTime.parse("2017-11-15T08:22:12"));
temporalValues.setOffsetDateTime(
  OffsetDateTime.parse("2017-11-15T08:22:12+01:00"));
temporalValues.setZonedDateTime(
  ZonedDateTime.parse("2017-11-15T08:22:12+01:00[Europe/Paris]"));


8結論

この記事では、Hibernateでさまざまなタイプの時間値をマッピングする方法を説明しました。

この記事のソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/hibernate5[GitHubで利用可能]です。