การทำแผนที่วันที่

มีอยู่

4.1 อรรถาธิบายสู่ประวัติศาสตร์

งานบันทึกวัตถุ Java ลงในฐานข้อมูลนั้นเกี่ยวข้องกันแทบจะในทันทีหลังจากสร้างภาษา Java ในเวลานั้น ภาษา Java มีข้อมูลประเภทเดียวคือ Date ซึ่งเก็บเวลาตามมาตรฐาน UNIX-time เป็นจำนวนมิลลิวินาทีตั้งแต่ปี 1970

ในฐานข้อมูลในเวลานั้นมีประเภทข้อมูลที่แตกต่างกันสำหรับวันที่ อย่างน้อยก็มีประเภทแยกต่างหากสำหรับวันที่ เวลา และวันที่ + เวลา:

  • วันที่
  • เวลา
  • ประทับเวลา

ดังนั้นผู้สร้างภาษา Java จึงเพิ่มแพ็คเกจพิเศษ - java.sql ซึ่งมีคลาส:

  • java.sql.date
  • java.sql.Time
  • java.sql.timestamp

การทำแผนที่ชั้นเรียนเหล่านี้เป็นเรื่องที่น่ายินดีอย่างยิ่ง:

@Entity
public class TemporalValues {

	@Basic
    private java.sql.Date sqlDate;

	@Basic
    private java.sql.Time sqlTime;

    @Basic
    private java.sql.Timestamp sqlTimestamp;
}

แต่เนื่องจากโปรแกรมเมอร์เคยทำงานกับคลาสjava.util.DateHibernate จึงเพิ่มคำอธิบายประกอบพิเศษ@Temporalเพื่อควบคุมการแมปของประเภทวันที่

ตัวอย่าง:

// If the annotation is missing, then the database will have a TIMESTAMP type
Date dateAsTimestamp;

@Temporal(TemporalType.DATE) // will be mapped to DATE type
Date dateAsDate;

@Temporal(TemporalType.TIME) // will be mapped to TIME type
Date dateAsTime;

ประเภทjava.util.Calendarและjava.util.Dateประเภทเริ่มต้นใช้ ประเภท TIMESTAMPเพื่อเป็นตัวแทนในฐานข้อมูล

4.2 เวลาใหม่

ในปัจจุบัน การทำแผนที่ทำให้ทุกอย่างง่ายขึ้นและดีขึ้นมาก ฐานข้อมูลทั้งหมดรองรับข้อมูล 4 ประเภทเพื่อทำงานกับเวลา:

  • DATE - วันที่: ปี เดือน และวัน
  • TIME - เวลา: ชั่วโมง นาที วินาที
  • TIMESTAMP - วันที่ เวลา และนาโนวินาที
  • การประทับเวลาด้วยโซนเวลา - การประทับเวลาและโซนเวลา (ชื่อโซนหรือออฟเซ็ต)

เพื่อแสดงถึงประเภท วันที่ใน Java คุณต้องใช้คลาสjava.time.LocalDateจาก JDK 8 DateTime API

พิมพ์เวลาจากฐานข้อมูลสามารถแสดงด้วยสองประเภทจาก Java: java.time.LocalTimeและjava.time.OffsetTime. ไม่มีอะไรซับซ้อน

และวันที่และเวลาที่แน่นอนแสดงตามประเภทประทับเวลาในฐานใน Java สามารถแสดงได้ 4 ประเภท:

  • java.time.Instant
  • java.time.LocalDateTime
  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

และในที่สุดก็ประทับเวลาด้วยโซนเวลาสามารถแสดงได้สองประเภท:

  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

เนื่องจากคุณคุ้นเคยกับDateTime API แล้ว การจำเรื่องนี้จึงไม่ใช่เรื่องยากสำหรับคุณ :)

การทำแผนที่เป็นความสุขอย่างแท้จริง:

@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หมายความว่าฟิลด์ควรได้รับการประมวลผลโดยอัตโนมัติ : ไฮเบอร์เนตจะตัดสินใจว่าคอลัมน์ใดและประเภทใดที่ควรแมปฟิลด์นี้

4.3 การทำงานกับโซนเวลา

หากเขตเวลาเป็นส่วนหนึ่งของวันที่ การจัดเก็บข้อมูลเหล่านั้นในฐานข้อมูลก็เป็นเรื่องง่าย เช่นเดียวกับวันที่ทั่วไป:

@Basic
private java.time.OffsetDateTime offsetDateTime;

@Basic
private java.time.ZonedDateTime zonedDateTime;

อย่างไรก็ตาม หากคุณต้องการจัดเก็บเขตเวลาแยกจากวันที่:

@Basic
private java.time.TimeZone timeZone;

@Basic
private java.time.ZoneOffset zonedOffset;

จากนั้น Hibernate จะจัดเก็บไว้ในประเภท VARCHAR ตามค่าเริ่มต้น ซึ่งอันที่จริงแล้วเป็นตรรกะ เนื่องจาก TimeZone มักจะมีชื่อสตริงเช่น "UTC + 3" หรือ "Cairo"

4.4 การตั้งค่าเขตเวลาของคุณเอง

เมื่อคุณทำงานกับการบันทึกวันที่ลงในฐานข้อมูล คุณจะพบว่ามีสถานที่ 4 แห่งที่คุณสามารถตั้งค่าเขตเวลาปัจจุบันได้:

  • ระบบปฏิบัติการเซิร์ฟเวอร์
  • ดีบีเอ็มเอส;
  • แอปพลิเคชันจาวา
  • ไฮเบอร์เนต

หาก DBMS ไม่ได้ระบุเขตเวลา (TimeZone) ระบบจะนำเขตเวลานั้นมาจากการตั้งค่าระบบปฏิบัติการ สิ่งนี้อาจไม่สะดวก เนื่องจาก DBMS สำรองมักจะอยู่ในศูนย์ข้อมูลอื่นที่มีเขตเวลาของตนเอง

ดังนั้น ผู้ดูแลระบบ DBMS เกือบทั้งหมดจึงตั้งค่าโซนเดียวเพื่อให้สามารถถ่ายโอนข้อมูลจากเซิร์ฟเวอร์หนึ่งไปยังอีกเซิร์ฟเวอร์หนึ่งได้อย่างง่ายดาย

สถานการณ์คล้ายกับแอปพลิเคชัน Java นอกจากนี้ยังสามารถทำงานบนเซิร์ฟเวอร์ที่แตกต่างกันในศูนย์ข้อมูลต่างๆ ดังนั้นจึงมักจะมีเขตเวลาที่ชัดเจน

java -Duser.timezone=UTC ...

หรือในขณะที่โปรแกรมกำลังทำงาน:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

และแน่นอนว่า Hibernate ให้คุณตั้งค่าโซนเวลาได้อย่างชัดเจน

อย่างแรก สามารถระบุได้เมื่อกำหนดค่า SessionFactory:

settings.put(
    AvailableSettings.JDBC_TIME_ZONE,
    TimeZone.getTimeZone("UTC")
);

ประการที่สองสามารถระบุเขตเวลาได้สำหรับเซสชั่นเฉพาะ:

Session session = sessionFactory()
    .withOptions()
    .jdbcTimeZone(TimeZone.getTimeZone("UTC"))
    .openSession();

4.5 คำอธิบายประกอบ @TimeZoneStorage

บ่อยครั้งที่โปรแกรมเมอร์เริ่มออกแบบฐานข้อมูลตามการทำงานในประเทศหนึ่ง (และโซนเวลาเดียว) และหลังจากนั้นสองสามปี พวกเขาจำเป็นต้องเพิ่มการสนับสนุนสำหรับการทำงานในโซนเวลาที่ต่างกัน

ดังนั้น พวกเขาจึงเพิ่มคอลัมน์แยกต่างหากในฐานข้อมูลเพื่อจัดเก็บโซนเวลา นี่เป็นสถานการณ์ทั่วไปที่ไฮเบอร์เนตได้เพิ่มคำอธิบายประกอบพิเศษที่ให้คุณจัดเก็บโซนเวลาของวันที่ที่ระบุในคอลัมน์แยกต่างหาก

ตัวอย่าง:

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

นี่คือไม้ค้ำยัน แต่ก็มีข้อแก้ตัวเช่นกัน: ปรากฏในเวลาที่ DateTime API ยังไม่มีอยู่ และเป็นไปไม่ได้ที่จะจัดเก็บ TimeZone ในชั้นjava.util.Dateเรียน

ฉันหวังว่าคุณจะไม่เห็นสิ่งนี้ในโค้ดของคุณบ่อยๆ

ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ