JPA 2.2 Sokongan untuk Java 8 Jenis Tarikh / Masa

1. Gambaran keseluruhan

Versi JPA 2.2 secara rasmi memperkenalkan sokongan untuk Java 8 Date and Time API. Sebelum itu, kita mesti bergantung pada penyelesaian berpemilik, atau kita harus menggunakan JPA Converter API.

Dalam tutorial ini, kami akan menunjukkan cara memetakan berbagai jenis Tarikh dan Waktu Java 8 . Kami akan memberi tumpuan terutamanya kepada yang mengambil kira maklumat pengimbangan.

2. Pergantungan Maven

Sebelum memulakan, kita perlu memasukkan API JPA 2.2 ke jalan kelas projek. Dalam projek berasaskan Maven, kita hanya dapat menambahkan kebergantungannya ke fail pom.xml kami :

 javax.persistence javax.persistence-api 2.2 

Selain itu, untuk menjalankan projek, kami memerlukan pelaksanaan JPA dan pemacu JDBC pangkalan data yang akan kami bekerjasama. Dalam tutorial ini, kami akan menggunakan EclipseLink dan pangkalan data PostgreSQL:

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

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

Sudah tentu, kita boleh menggunakan pangkalan data lain atau pelaksanaan JPA seperti Hibernate.

3. Sokongan Zon Waktu

Kita boleh bekerja dengan pangkalan data mana pun, tetapi pertama, kita harus memeriksa sokongan untuk Jenis SQL Standard ini, kerana JDBC 4.2 didasarkan pada:

  • TIMESTAMP (n) DENGAN ZON MASA
  • TIMESTAMP (n) TANPA ZON MASA
  • MASA (n) DENGAN ZON MASA
  • MASA (n) TANPA ZON MASA

Di sini, n adalah ketepatan pecahan detik dan antara 0 hingga 9 digit. TANPA ZON WAKTU adalah pilihan dan boleh dihilangkan. Sekiranya DENGAN ZON WAKTU ditentukan, nama zon waktu atau ofset ke UTC diperlukan.

Kami dapat mewakili zon waktu dalam salah satu daripada dua format berikut:

  • Nama zon waktu
  • Mengimbangi dari UTC atau huruf Z untuk UTC

Sebagai contoh, kami telah memilih pangkalan data PostgreSQL berkat sokongan penuh untuk SQL Type TIME WITH TIME ZONE .

Perhatikan bahawa pangkalan data lain mungkin tidak menyokong jenis ini.

4. Pemetaan Jenis Tarikh Sebelum Java 8

Sebelum Java 8, kita biasanya terpaksa memetakan jenis SQL generik TIME, DATE , dan TIMESTAMP , sama ada kepada java.sql. * Kelas java.sql.Time , java.sql.Date, dan java.sql.Timestamp, masing-masing, atau ke java.util jenis java.util.Date dan java.util.Calendar .

Pertama, mari kita lihat cara menggunakan jenis java.sql . Di sini, kami hanya menentukan atribut dengan jenis java.sql sebagai sebahagian daripada kelas @Entity :

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

Walaupun jenis java.sql berfungsi seperti jenis lain tanpa pemetaan tambahan, jenis java.util perlu menentukan jenis temporal yang sesuai.

Ini dilakukan melalui anotasi @Temporal yang atribut nilainya memungkinkan kita menentukan jenis JDBC yang sesuai, menggunakan penghitungan 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 bahawa jika kita menggunakan Hibernate sebagai implementasi, ini tidak menyokong pemetaan Kalendar hingga TIME .

Begitu juga, kita boleh menggunakan kelas Kalendar :

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

Tiada jenis ini yang menyokong zon waktu atau ofset. Untuk menangani maklumat tersebut, kami secara tradisinya menyimpan masa UTC.

5. Memetakan Java 8 Jenis Tarikh

Java 8 telah memperkenalkan pakej java.time , dan JDBC 4.2 API menambahkan sokongan untuk jenis SQL tambahan TIMESTAMP WITH TIME ZONE dan TIME WITH TIME ZONE .

Kami kini boleh memetakan JDBC Jenis TIME, DATE, dan TIMESTAMP kepada 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 mempunyai sokongan untuk mengimbangi zon waktu tempatan 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 lajur yang dipetakan sesuai mestilah TIME WITH TIME ZONE dan TIMESTAMP WITH TIME ZONE . Malangnya, tidak semua pangkalan data menyokong kedua-dua jenis ini.

Seperti yang kita lihat, JPA menyokong lima kelas ini sebagai jenis asas, dan tidak ada maklumat tambahan yang diperlukan untuk membezakan antara tarikh dan / atau maklumat waktu.

Setelah menyimpan contoh baru kelas entiti kami, kami dapat memeriksa bahawa data telah dimasukkan dengan betul:

6. Kesimpulannya

Sebelum Java 8 dan JPA 2.2, pemaju biasanya harus menukar jenis tarikh / waktu ke UTC sebelum meneruskannya. JPA 2.2 kini menyokong ciri ini di luar kotak dengan menyokong pengimbangan ke UTC dan dengan memanfaatkan sokongan JDBC 4.2 untuk zon waktu.

Kod sumber penuh untuk sampel ini boleh didapati di Github.