4.1 Tarixiy koʻrinish
Java obyektlarini ma'lumotlar bazasida saqlash masalasi Java tilini yaratish bilanoq dolzarb bo'lgan. O'sha vaqtda Java tilida faqat bitta ma'lumot turi - Date mavjud edi, UNIX-time standarti bo'yicha vaqtni saqlardi: 1970 yildan beri o'tgan millisekundlar soni sifatida.
Lekin o'sha paytda ma'lumotlar bazalarida sanalar uchun turli tiplar mavjud edi, kamida sanalar uchun alohida tiplar mavjud edi:
- DATE
- TIME
- TIMESTAMP
Shuning uchun Java tilini yaratuvchilar unga maxsus paket qo'shishdi – java.sql, bu paket quyidagi klasslarni o'z ichiga oladi:
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
Ana shunday klasslar bilan ishlash ancha oson:
@Entity
public class TemporalValues {
@Basic
private java.sql.Date sqlDate;
@Basic
private java.sql.Time sqlTime;
@Basic
private java.sql.Timestamp sqlTimestamp;
}
Lekin ilgari dasturchilar java.util.Date classi bilan ishlashi kerak edi, shuning uchun Hibernate'ga @Temporal annotatsiyasini qo'shishdi, bu Date turini mapping qilishni boshqarish uchun edi.
Misol:
// Agar anotatsiya mavjud bo'lmasa, bazada TIMESTAMP turi bo'ladi
Date dateAsTimestamp;
@Temporal(TemporalType.DATE) // DATE turiga mapping qilinadi
Date dateAsDate;
@Temporal(TemporalType.TIME) // TIME turiga mapping qilinadi
Date dateAsTime;
java.util.Calendar va java.util.Date turlari uchun bazada ularning ko'rinishi uchun TIMESTAMP turi standart bo'lib ishlatiladi.
4.2 Yangi davr
Hozirgi vaqtda mapping bilan harakat qilish ancha oson va yaxshi. Barcha ma'lumotlar bazalari vaqt bilan ishlash uchun 4 tur ma'lumot turini qo'llab-quvvatlaydi:
- DATE – sana: yil, oy va kun.
- TIME – vaqt: soat, daqiqa, soniya.
- TIMESTAMP – sana, vaqt va nanosoniyalar.
- TIMESTAMP WITH TIME ZONE – TIMESTAMP va vaqt zonasi (zona nomi yoki ofset).
DATE turini Java'da tasvirlash uchun JDK 8 DateTime API'dan java.time.LocalDate klassidan foydalanish kerak.
Ma'lumotlar bazasidagi TIME turini Java'da ikkita tur bilan tasvirlash mumkin: java.time.LocalTime va java.time.OffsetTime. Bunda hech qiyinchilik yo'q.
Ma'lumotlar bazasidagi TIMESTAMP bilan ko‘rsatilgan aniq sana va vaqtni Java’da 4 tur bilan tasvirlash mumkin:
- java.time.Instant
- java.time.LocalDateTime
- java.time.OffsetDateTime
- java.time.ZonedDateTime
Nihoyat TIMESTAMP WITH TIME ZONE ni ikki tur bilan tasvirlash mumkin:
- java.time.OffsetDateTime
- java.time.ZonedDateTime
DateTime API bilan tanish bo‘lganing uchun buni o‘rganish senga qiyinchilik tug‘dirmaydi :)
Ularni mapping qilish bir zavq:
@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;
@Basic annotatsiyasi maydonni avtomatik ravishda qayta ishlanishi kerakligini anglatadi: Hibernate maydonni qaysi ustun va turga mapping qilish kerakligini o'zi hal qiladi.
4.3 Vaqt zonalari bilan ishlash
Agar vaqt zonasi sananing bir qismi bo'lsa, ularni bazada saqlash oson - oddiy sana kabi:
@Basic
private java.time.OffsetDateTime offsetDateTime;
@Basic
private java.time.ZonedDateTime zonedDateTime;
Lekin, agar vaqt zonalarini sanadan alohida saqlamoqchi bo'lsang:
@Basic
private java.time.TimeZone timeZone;
@Basic
private java.time.ZoneOffset zonedOffset;
Unda Hibernate ularni VARCHAR turida saqlashni standart qilib qo'yadi. Bu aslida mantiqan to'g'ri, chunki TimeZone odatda "UTC+3" yoki "Cairo" kabi qator nomga ega bo'ladi.
4.4 O'z vaqt zonasini o'rnatish
Sanalarning ma'lumotlar bazasiga saqlanishi bilan ishlaganda, mavjud vaqt zonasi bilan ishlashda 4 ta joy mavjudligini topasan:
- Serverning operatsion tizimi;
- DBMS;
- Java ilovasi;
- Hibernate.
Agar DBMSda vaqt zonasi (TimeZone) ko'rsatilmagan bo'lsa, u operatsion tizim sozlamalaridan oladi. Bu noqulay bo'lishi mumkin, chunki zaxira DBMSlar ko'pincha boshqa ma'lumotlar markazlarida joylashtiriladi, ular esa o'z vaqt zonasiga ega.
Shu sababli, deyarli barcha DBMS administratorlari bir xil zonani o'rnatadilar, shunda ma'lumotlarni bir serverdan boshqasiga osongina ko'chirish mumkin.
Java ilovasida ham shunday holat bo'ladi. Bu ham turli serverlarda, turli ma'lumotlar markazlarida ishlashi mumkin, shuning uchun unga odatda vaqt zonasi aniq belgilanadi.
java -Duser.timezone=UTC ...
Yoki dastur ishlayotgan paytda:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Albatta, Hibernate o'z vaqt zonasini aniq belgilashga imkon beradi.
Birinchidan, uni SessionFactory ni sozlashda ko'rsatish mumkin:
settings.put(
AvailableSettings.JDBC_TIME_ZONE,
TimeZone.getTimeZone("UTC")
);
Ikkinchidan, vaqt zonasini ma’lum bir sessiya uchun ko'rsatish mumkin:
Session session = sessionFactory()
.withOptions()
.jdbcTimeZone(TimeZone.getTimeZone("UTC"))
.openSession();
4.5 @TimeZoneStorage annotatsiyasi
Ko'pincha dasturchilar bir davlatda (va bir vaqt zonasida) ishlash uchun ma'lumotlar bazasini loyihalashni boshladilar va keyin bir necha yildan keyin turli vaqt zonalarida ishlashni qo'llab-quvvatlashni qo'shishlari kerak bo'ladi.
Shuning uchun ular ma'lumotlar bazasiga vaqt zonasini saqlash uchun alohida ustun qo'shishadi. Bu juda keng tarqalgan holat, shuning uchun Hibernate belgilangan sananing vaqt zonasini alohida ustunda saqlash imkonini beruvchi maxsus anotatsiyani qo'shdi.
Misol:
@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_offset_offset")
@Column(name = "birthday_offset")
private OffsetDateTime offsetDateTimeColumn;
@TimeZoneStorage(TimeZoneStorageType.COLUMN)
@TimeZoneColumn(name = "birthday_zoned_offset")
@Column(name = "birthday_zoned")
private ZonedDateTime zonedDateTimeColumn;
Bu bir turdagi kostil. Lekin unga ham asos bor: u DateTime API mavjud bo'lmagan paytlarda paydo bo'lgan. java.util.Date klassida TimeZone ni saqlash mumkin emas edi.
Umid qilamanki, buni kodingda tez-tez uchratmaysan.
GO TO FULL VERSION