sql >> Databáze >  >> RDS >> Mysql

Jak uložit Java Instant v databázi MySQL

Zkrácení na mikrosekundy

Je zřejmé, že nemůžeme zmáčknout nanosekundy rozlišení Instant do mikrosekund rozlišení datových typů MySQL DateTime a Timestamp .

I když nepoužívám MySQL, představuji si ovladač JDBC je vytvořen tak, aby ignoroval nanosekundy při příjmu Instant , zkrátí hodnotu na mikrosekundy. Doporučuji zkusit experiment, abyste viděli a možná prozkoumali zdrojový kód vašeho ovladače, který vyhovuje JDBC 4.2 a novějším.

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

…a…

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

Specifikace JDBC 4.2 vyžaduje podporu pro OffsetDateTime ale kupodivu nevyžaduje dva běžně používané typy, Instant a ZonedDateTime . Pokud váš ovladač JDBC nepodporuje Instant , převést.

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

Pak porovnejte.

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

Jste moudře znepokojeni hodnotami získanými z databáze, které neodpovídají původní hodnotě. Jedním z řešení, pokud je to přijatelné pro váš obchodní problém, je zkrátit jakékoli nanosekundy na mikrosekundy v původních datech. Tento přístup obecně doporučuji.

java.time třídy nabízejí truncatedTo metoda. Předejte ChronoUnit objekt enum k určení granularity. V tomto případě by to bylo ChronoUnit.MICROS .

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

V současné době by tento přístup měl stačit, protože je nepravděpodobné, že byste ve svých datech měli nějaké nanosekundy. Mainstreamové počítače dnes nemají hardwarové hodiny schopné zachytit nanosekundy, pokud vím.

Počítání od epoch

Pokud si nemůžete dovolit ztratit jakákoliv nanosekundová data, která mohou být přítomna, použijte počítání od epochy.

Obvykle nedoporučuji sledovat datum a čas jako počet od referenčního data epochy. Ale máte několik dalších možností při ukládání hodnot na bázi nanosekund v databázi, jako je MySQL a Postgres, omezená na hodnoty založené na mikrosekundách.

Uložte pár celých čísel

Spíše než používat extrémně velký počet nanosekund od epochy, jako je 1970-01-01T00:00Z, navrhuji následovat přístup, který zvolili vnitřnosti Instant třída:Použijte pár čísel.

Uložte počet celek sekund jako celé číslo ve vaší databázi. Ve druhém sloupci uložte jako celé číslo počet nanosekund ve zlomkové sekundě.

Tato čísla můžete snadno extrahovat/vložit z/do Instant objekt. Pouze jednoduchý 64bitový long jde o čísla; není potřeba BigDecimal nebo BigInteger . Předpokládám, že byste mohli být schopni použít 32bitový celočíselný sloupec alespoň pro jedno ze dvou čísel. Ale zvolil bych 64bitové celočíselné typy sloupců pro jednoduchost a pro přímou kompatibilitu s java.time.Instant třídy‘ pár dlouhých.

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

…a…

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

Při chronologickém řazení budete muset provést víceúrovňové řazení, nejprve seřadit podle sloupce s celými sekundami a poté seřadit sekundárně podle sloupce se zlomkem sekundy nano.




  1. SQL Server Transakční replikace interní

  2. Změna časového pásma připojení v MySQL

  3. Co když potřebuji velmi velké ID automatického přírůstku?

  4. Jak vložit datovou tabulku do databázové tabulky SQL Serveru?