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

Cách lưu trữ Java Instant trong cơ sở dữ liệu MySQL

Cắt ngắn thành micro giây

Rõ ràng là chúng ta không thể sử dụng nano giây độ phân giải của Instant vào micro giây độ phân giải của kiểu dữ liệu MySQL DateTimeTimestamp .

Trong khi tôi không sử dụng MySQL, tôi tưởng tượng ra trình điều khiển JDBC được xây dựng để bỏ qua nano giây khi nhận được Instant , cắt ngắn giá trị thành micro giây. Tôi khuyên bạn nên thử một thử nghiệm để xem và có thể kiểm tra mã nguồn của trình điều khiển của bạn có tuân thủ JDBC 4.2 trở lên không.

Instant instant = Instant.now().with( ChronoField.NANO_OF_SECOND , 123_456_789L ) ;  //Set the fractional second to a spefic number of nanoseconds.
myPreparedStatement.setObject( … , instant ) ;

… Và…

Instant instant2 = myResultSet.getObject( … , Instant.class ) ;

Thông số kỹ thuật JDBC 4.2 yêu cầu hỗ trợ cho OffsetDateTime nhưng kỳ lạ là không yêu cầu hai loại thường được sử dụng hơn, InstantZonedDateTime . Nếu trình điều khiển JDBC của bạn không hỗ trợ Instant , chuyển đổi.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;  // Use `OffsetDateTime` if your JDBC driver does not support `Instant`. 
Instant instant2 = odt.toInstant() ;  // Convert from `OffsetDateTime` to `Instant`. 

Sau đó so sánh.

Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;

Bạn lo lắng một cách khôn ngoan về các giá trị được rút ra từ cơ sở dữ liệu không khớp với giá trị ban đầu. Một giải pháp, nếu có thể chấp nhận được đối với vấn đề kinh doanh của bạn, là cắt ngắn bất kỳ nano giây nào thành micro giây trong dữ liệu gốc của bạn. Tôi khuyến nghị cách tiếp cận này nói chung.

java.time các lớp cung cấp truncatedTo phương pháp. Chuyển ChronoUnit đối tượng enum để chỉ định mức độ chi tiết. Trong trường hợp này, đó sẽ là ChronoUnit.MICROS .

Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;

Hiện tại, cách tiếp cận này sẽ đủ vì bạn không có khả năng có bất kỳ nano giây nào trong dữ liệu của mình. Theo tôi biết, các máy tính phổ thông ngày nay không có đồng hồ phần cứng có khả năng bắt nano giây.

Đếm từ kỷ nguyên

Nếu bạn không đủ khả năng để mất bất kỳ dữ liệu nano giây nào có thể có, hãy sử dụng đếm từ kỷ nguyên.

Tôi thường khuyên bạn không nên theo dõi ngày-giờ dưới dạng số đếm từ ngày tham chiếu kỷ nguyên. Nhưng bạn có một số lựa chọn khác trong việc lưu trữ các giá trị dựa trên nano giây của mình trong cơ sở dữ liệu như MySQL và Postgres được giới hạn ở các giá trị dựa trên micro giây.

Lưu trữ cặp số nguyên

Thay vì sử dụng số lượng nano giây cực lớn kể từ một kỷ nguyên chẳng hạn như 1970-01-01T00:00Z, tôi khuyên bạn nên làm theo phương pháp được thực hiện bởi bên trong của Instant lớp:Sử dụng một cặp trong số các con số.

Lưu trữ một số toàn bộ giây dưới dạng số nguyên trong cơ sở dữ liệu của bạn. Trong cột thứ hai lưu trữ dưới dạng số nguyên, số nano giây trong giây phân số.

Bạn có thể dễ dàng trích xuất / đưa các số này vào / vào Instant vật. Chỉ long 64-bit đơn giản các con số có liên quan; không cần BigDecimal hoặc BigInteger . Tôi cho rằng bạn có thể sử dụng cột số nguyên 32 bit cho ít nhất một trong hai số. Nhưng tôi sẽ chọn các loại cột số nguyên 64-bit để đơn giản và tương thích trực tiếp với java.time.Instant đôi long của lớp.

long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;

… Và…

Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;

Khi sắp xếp theo thứ tự thời gian, bạn sẽ cần thực hiện sắp xếp nhiều cấp, trước tiên sắp xếp trên toàn bộ cột giây và sau đó sắp xếp thứ hai trên cột phần giây nano.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hibernate OnDelete Cascade không hoạt động cho MySql nhưng hoạt động trên postgres và Ms-Sql

  2. Tạo lại com.mysql.jdbc.exceptions.jdbc4.CommunicationsException với thiết lập Spring, hibernate và C3P0

  3. MySQL JOIN / GROUP_CONCAT bảng thứ hai?

  4. MySql Proccesslist chứa đầy các Mục nhập Ngủ dẫn đến Quá nhiều Kết nối?

  5. kết nối với máy chủ MySQL cục bộ thông qua socket