Hibernate–日付と時刻のマッピング
1. 序章
この記事では、 java .sql 、 java .util 、 javaのクラスを含む、Hibernateの時間列値をマップする方法を示します。 ].timeパッケージ。
2. プロジェクトの設定
時間型のマッピングを示すために、H2データベースと最新バージョンのhibernate-coreライブラリが必要になります。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.12.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.194</version>
</dependency>
hibernate-core ライブラリの現在のバージョンについては、 MavenCentralリポジトリにアクセスしてください。
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 には、最大ナノ秒の精度で日付と時刻に関する情報が含まれ、 TIMESTAMPSQLタイプに対応します。
これらのタイプは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タイプ
タイプjava.util.Dateには、最大ミリ秒の精度で日付と時刻の両方の情報が含まれます。ただし、SQLタイプとは直接関係ありません。
これが、目的の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;
The @Temporal アノテーションには、タイプの単一のパラメーター値があります
次に、対応するフィールドを次のように設定できます。
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.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 andTimeAPIが使用可能になりました。 このAPIは、java.util.Dateおよびjava.util.Calendarクラスの問題の多くを修正します。
java.time パッケージの型は、対応するSQL型に直接マップされます。 したがって、@Temporalアノテーションを明示的に指定する必要はありません。
- LocalDateはDATEにマップされます
- LocalTimeおよびOffsetTimeはTIMEにマップされます
- Instant 、 LocalDateTime 、 ResetDateTime 、および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でさまざまなタイプの時間値をマップする方法を示しました。
この記事のソースコードは、GitHubでから入手できます。