Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak przechowywać Java Instant w bazie danych MySQL

Skróć do mikrosekund

Oczywiście nie możemy wycisnąć nanosekund rozdzielczość Instant w mikrosekundy rozdzielczość typów danych MySQL DateTime i Timestamp .

Chociaż nie używam MySQL, wyobrażam sobie sterownik JDBC jest zbudowany tak, aby ignorować nanosekundy podczas odbierania Instant , obcinając wartość do mikrosekund. Proponuję spróbować eksperymentu, aby zobaczyć i być może zbadać kod źródłowy sterownika, który jest zgodny z JDBC 4.2 i nowszymi.

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

…i…

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

specyfikacja JDBC 4.2 wymaga obsługi OffsetDateTime ale, co dziwne, nie wymaga dwóch częściej używanych typów, Instant i ZonedDateTime . Jeśli Twój sterownik JDBC nie obsługuje Instant , przekonwertuj.

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`. 

Następnie porównaj.

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

Mądrze obawiasz się, że wartości pobierane z bazy danych nie pasują do oryginalnej wartości. Jednym z rozwiązań, jeśli jest to akceptowalne dla Twojego problemu biznesowego, jest skrócenie dowolnych nanosekund do mikrosekund w oryginalnych danych. Generalnie polecam to podejście.

java.time zajęcia oferują truncatedTo metoda. Przekaż ChronoUnit obiekt enum, aby określić szczegółowość. W tym przypadku byłoby to ChronoUnit.MICROS .

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

Obecnie to podejście powinno wystarczyć, ponieważ jest mało prawdopodobne, aby Twoje dane zawierały nanosekundy. O ile mi wiadomo, komputery głównego nurtu nie mają zegarów sprzętowych zdolnych do przechwytywania nanosekund.

Odliczanie od epoki

Jeśli nie możesz sobie pozwolić na utratę jakichkolwiek danych nanosekundowych, które mogą być obecne, użyj liczenia od epoki.

Zwykle odradzam śledzenie daty i czasu jako liczby od daty odniesienia epoki. Ale masz kilka innych możliwości przechowywania wartości opartych na nanosekundach w bazie danych, takich jak MySQL i Postgres, ograniczonych do wartości opartych na mikrosekundach.

Przechowuj parę liczb całkowitych

Zamiast korzystać z niezwykle dużej liczby nanosekund od epoki, takiej jak 1970-01-01T00:00Z, sugeruję podejście przyjęte przez wewnętrzne elementy Instant klasa:Użyj pary liczb.

Przechowuj kilka całości sekund jako liczba całkowita w Twojej bazie danych. W drugiej kolumnie zapisz jako liczbę całkowitą liczbę nanosekund w ułamku sekundy.

Możesz łatwo wyodrębnić/wstrzyknąć te liczby z/do Instant obiekt. Tylko proste 64-bitowe long liczby są zaangażowane; nie ma potrzeby używania BigDecimal lub BigInteger . Przypuszczam, że możesz użyć 32-bitowej kolumny liczb całkowitych dla co najmniej jednej z dwóch liczb. Ale wybrałbym 64-bitowe typy kolumn całkowitych dla uproszczenia i bezpośredniej zgodności z java.time.Instant para długich spodni klasy.

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

…i…

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

Podczas sortowania chronologicznego musisz wykonać sortowanie wielopoziomowe, najpierw sortując według całej kolumny sekund, a następnie sortując wtórnie według ułamka sekundy w nanos.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql_fetch_array() oczekuje, że parametr 1 będzie problemem z zasobami

  2. CONCAT wiele pól do jednego pola, z pojedynczym odstępem

  3. Hibernacja strategii nazewnictwa zmieniającej nazwy tabel

  4. Codeigniter/PHP sprawdza, czy można połączyć się z bazą danych

  5. Mysql niespójna liczba wierszy count(*) vs table.table_rows w information_schema