Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

JPA Lưu sai ngày trong cơ sở dữ liệu MySQL

tl; dr

Sử dụng JPA 2.2 để được hỗ trợ java.time .

Sử dụng lớp chỉ ngày trong Java để làm việc với các giá trị chỉ ngày trong SQL.

LocalDate                           // Represent a date-only, without a time-of-day and without a time zone.
.now(                               // Get today's date…
    ZoneId.of( "Africa/Tunis" )     // …as seen in the wall-clock time used by the people of a particular region.
)                                   // Returns a `LocalDate` object.
.plusMonths( 1 )                    // Returns another `LocalDate` object, per immutable objects pattern.

java.time

JPA 2.2 hiện hỗ trợ java.time hiện đại các lớp học. Không cần sử dụng Joda-Time nữa.

Không không sử dụng java.sql.Date . Lớp đó giả vờ để đại diện cho ngày chỉ nhưng thực sự có thời gian trong ngày được đặt thành UTC vì quyết định thiết kế khủng khiếp kế thừa từ java.util.Date (mặc dù tên đại diện cho một ngày thời gian trong ngày độ lệch 0 cho chính UTC). Những lớp kế thừa này là một mớ hỗn độn tồi tệ. Sun, Oracle và cộng đồng JCP đều đã từ bỏ các lớp luận văn nhiều năm trước khi áp dụng JSR 310, và bạn cũng vậy.

LocalDate

LocalDate lớp đại diện cho giá trị chỉ ngày không có thời gian trong ngày và không có múi giờ hoặc offset-from-UTC .

Múi giờ rất quan trọng trong việc xác định ngày. Đối với bất kỳ thời điểm cụ thể nào, ngày thay đổi trên toàn cầu theo khu vực. Ví dụ:vài phút sau nửa đêm ở Paris Pháp là một ngày mới trong khi vẫn là “ngày hôm qua” trong Montréal Québec .

Nếu không có múi giờ nào được chỉ định, JVM sẽ áp dụng hoàn toàn múi giờ mặc định hiện tại của nó. Mặc định đó có thể thay đổi bất kỳ lúc nào trong thời gian chạy (!), vì vậy kết quả của bạn có thể khác nhau. Tốt hơn là chỉ định múi giờ mong muốn / dự kiến ​​của bạn một cách rõ ràng như một đối số. Nếu quan trọng, hãy xác nhận khu vực với người dùng của bạn.

Chỉ định tên múi giờ thích hợp ở định dạng Continent/Region , chẳng hạn như America/Montreal , Africa/Casablanca hoặc Pacific/Auckland . Không bao giờ sử dụng từ viết tắt 2-4 chữ cái, chẳng hạn như EST hoặc IST vì họ không không múi giờ đúng, không được tiêu chuẩn hóa và thậm chí không phải là duy nhất (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Nếu bạn muốn sử dụng múi giờ mặc định hiện tại của JVM, hãy yêu cầu múi giờ đó và chuyển làm đối số. Nếu bị bỏ qua, mã sẽ trở nên mơ hồ khi đọc và chúng tôi không biết chắc chắn liệu bạn có định sử dụng mã mặc định hay không hoặc nếu bạn, giống như rất nhiều lập trình viên, không biết về vấn đề này.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Hoặc chỉ định một ngày. Bạn có thể đặt tháng bằng một số, với việc đánh số lành mạnh từ 1-12 cho tháng 1 đến tháng 12.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Hoặc, tốt hơn, hãy sử dụng Month các đối tượng enum được xác định trước, một đối tượng cho mỗi tháng trong năm. Mẹo:Sử dụng Month này các đối tượng trong toàn bộ cơ sở mã của bạn thay vì chỉ là một số nguyên để làm cho mã của bạn tự lập tài liệu hơn, đảm bảo các giá trị hợp lệ và cung cấp loại-an toàn . Ditto cho Year & YearMonth .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Toán ngày giờ

Rõ ràng bạn muốn bắt đầu với một ngày và lấy một tháng sau làm phạm vi ngày.

LocalDate monthLater = ld.plusMonths( 1 ) ;

JDBC 4.2

Kể từ JDBC 4.2, trình điều khiển JDBC của bạn được yêu cầu hỗ trợ một số khóa java.time các lớp như LocalDate .

Phạm vi ngày

Lưu ý các liên kết bên dưới cho ThreeTen-Extra . Bạn có thể tìm thấy LocalDateRange lớp ở đó sẽ hữu ích nếu bạn làm nhiều việc với phạm vi ngày.

Giới thiệu về java.time

java.time khung công tác được tích hợp vào Java 8 trở lên. Các lớp này thay thế cho kế thừa cũ rắc rối các lớp date-time chẳng hạn như java.util.Date , Calendar & SimpleDateFormat .

Để tìm hiểu thêm, hãy xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow để có nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Joda-Time dự án, hiện đang ở chế độ bảo trì , khuyên bạn nên di chuyển sang java.time các lớp học.

Bạn có thể trao đổi java.time các đối tượng trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tuân thủ JDBC 4.2 hoặc sau đó. Không cần chuỗi, không cần java.sql.* các lớp học.

Lấy các lớp java.time ở đâu?

ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là cơ sở chứng minh cho những bổ sung có thể có trong tương lai cho java.time. Bạn có thể tìm thấy một số lớp hữu ích tại đây, chẳng hạn như Interval , YearWeek , YearQuarter khác .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách sử dụng thẻ JSTL sql

  2. PDO - Số tham số không hợp lệ

  3. Thứ tự MySQL theo mức độ liên quan

  4. Sự cố mã hóa PDO UTF-8?

  5. Làm thế nào để kéo dữ liệu từ cơ sở dữ liệu mysql và trực quan hóa với D3.JS?