JPA 2.2 Dukungan untuk Java 8 Jenis Tanggal / Waktu

1. Ikhtisar

Versi JPA 2.2 secara resmi telah memperkenalkan dukungan untuk Java 8 Date and Time API. Sebelumnya, kami harus mengandalkan solusi berpemilik, atau kami harus menggunakan JPA Converter API.

Dalam tutorial ini, kami akan menunjukkan cara memetakan berbagai tipe Tanggal dan Waktu Java 8 . Kami akan secara khusus fokus pada salah satu yang memperhitungkan informasi offset.

2. Ketergantungan Maven

Sebelum kita mulai, kita perlu memasukkan JPA 2.2 API ke project classpath. Dalam proyek berbasis Maven, kita cukup menambahkan ketergantungannya ke file pom.xml kita :

 javax.persistence javax.persistence-api 2.2 

Selain itu, untuk menjalankan proyek, kami memerlukan implementasi JPA dan driver JDBC dari database yang akan kami tangani. Dalam tutorial ini, kita akan menggunakan EclipseLink dan database PostgreSQL:

 org.eclipse.persistence eclipselink 2.7.4 runtime   org.postgresql postgresql 42.2.5 runtime bundle 

Jangan ragu untuk memeriksa versi terbaru JPA API, EclipseLink, dan driver JDBC PostgreSQL di Maven Central.

Tentu saja, kita dapat menggunakan database lain atau implementasi JPA seperti Hibernate.

3. Dukungan TimeZone

Kami dapat bekerja dengan database apa pun, tetapi pertama-tama, kami harus memeriksa dukungan untuk Jenis SQL Standar ini, karena JDBC 4.2 didasarkan pada:

  • TIMESTAMP (n) DENGAN ZONA WAKTU
  • TIMESTAMP (n) TANPA ZONA WAKTU
  • WAKTU (n) DENGAN ZONA WAKTU
  • WAKTU (n) TANPA ZONA WAKTU

Di sini, n adalah ketepatan detik pecahan dan berada di antara 0 dan 9 digit. TANPA ZONA WAKTU bersifat opsional dan dapat dihilangkan. Jika DENGAN ZONA WAKTU ditentukan, nama zona waktu atau pengimbangan ke UTC diperlukan.

Kami dapat mewakili zona waktu dalam salah satu dari dua format berikut:

  • Nama zona waktu
  • Offset dari UTC atau huruf Z untuk UTC

Sebagai contoh, kami telah memilih database PostgreSQL berkat dukungan penuhnya untuk Jenis SQL WAKTU DENGAN ZONA WAKTU .

Perhatikan bahwa database lain mungkin tidak mendukung tipe ini.

4. Pemetaan Jenis Tanggal Sebelum Java 8

Sebelum Java 8, kita biasanya harus memetakan jenis generik SQL WAKTU, TANGGAL , dan TIMESTAMP , ke salah satu java.sql. * Kelas java.sql.Time , java.sql.Date, dan java.sql.Timestamp, masing-masing, atau untuk java.util jenis java.util.Date dan java.util.Calendar .

Pertama, mari kita lihat bagaimana menggunakan tipe java.sql . Di sini, kami hanya mendefinisikan atribut dengan tipe java.sql sebagai bagian dari kelas @Entity :

@Entity public class JPA22DateTimeEntity { private java.sql.Time sqlTime; private java.sql.Date sqlDate; private java.sql.Timestamp sqlTimestamp; // ... }

Sementara tipe java.sql bekerja seperti tipe lainnya tanpa pemetaan tambahan, tipe java.util perlu menentukan tipe temporal yang sesuai.

Ini dilakukan melalui anotasi @Temporal yang atribut nilainya memungkinkan kita menentukan jenis JDBC yang sesuai, menggunakan pencacahan TemporalType :

@Temporal(TemporalType.TIME) private java.util.Date utilTime; @Temporal(TemporalType.DATE) private java.util.Date utilDate; @Temporal(TemporalType.TIMESTAMP) private java.util.Date utilTimestamp;

Perhatikan bahwa jika kami menggunakan Hibernate sebagai implementasi, ini tidak mendukung pemetaan Kalender ke TIME .

Demikian pula, kita dapat menggunakan kelas Kalender :

@Temporal(TemporalType.TIME) private Calendar calendarTime; @Temporal(TemporalType.DATE) private Calendar calendarDate; @Temporal(TemporalType.TIMESTAMP) private Calendar calendarTimestamp;

Tak satu pun dari jenis ini memiliki dukungan untuk zona waktu atau offset. Untuk menangani potongan-potongan informasi itu, secara tradisional kami harus menyimpan waktu UTC.

5. Pemetaan Java 8 Jenis Tanggal

Java 8 telah memperkenalkan paket java.time , dan JDBC 4.2 API menambahkan dukungan untuk tipe SQL tambahan TIMESTAMP DENGAN ZONA WAKTU dan WAKTU DENGAN ZONA WAKTU .

Kita sekarang dapat memetakan JDBC Jenis WAKTU, TANGGAL, dan TIMESTAMP ke java.time jenis - localtime, LOCALDATE , dan 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;

Selain itu, kami memiliki dukungan untuk offset zona waktu lokal ke UTC melalui kelas OffsetTime dan OffsetDateTime :

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

Jenis kolom yang dipetakan sesuai harus TIME DENGAN ZONA WAKTU dan TIMESTAMP DENGAN ZONA WAKTU . Sayangnya, tidak semua database mendukung kedua tipe ini.

Seperti yang dapat kita lihat, JPA mendukung lima kelas ini sebagai tipe dasar, dan tidak ada informasi tambahan yang diperlukan untuk membedakan antara informasi tanggal dan / atau waktu.

Setelah menyimpan instance baru dari kelas entitas kami, kami dapat memeriksa bahwa data telah dimasukkan dengan benar:

6. Kesimpulan

Sebelum Java 8 dan JPA 2.2, pengembang biasanya harus mengonversi jenis tanggal / waktu ke UTC sebelum mempertahankannya. JPA 2.2 sekarang mendukung fitur ini di luar kotak dengan mendukung offset ke UTC dan dengan memanfaatkan dukungan JDBC 4.2 untuk zona waktu.

Kode sumber lengkap untuk sampel ini dapat ditemukan di Github.