sql >> Database >  >> RDS >> Mysql

Een Java Instant opslaan in een MySQL-database

Afkappen tot microseconden

Het is duidelijk dat we de nanoseconden niet kunnen persen resolutie van een Instant in de microseconden resolutie van de MySQL-gegevenstypen DateTime en Timestamp .

Hoewel ik MySQL niet gebruik, stel ik me de JDBC-stuurprogramma voor is gebouwd om de nanoseconden te negeren bij het ontvangen van een Instant , waarbij de waarde wordt afgekapt tot microseconden. Ik stel voor dat u een experiment probeert om de broncode van uw stuurprogramma te bekijken en misschien te onderzoeken die voldoet aan JDBC 4.2 en hoger.

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

…en…

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

De JDBC 4.2-specificatie vereist ondersteuning voor OffsetDateTime maar vereist vreemd genoeg niet de twee meest gebruikte typen, Instant en ZonedDateTime . Als uw JDBC-stuurprogramma ondersteunt Instant niet , converteren.

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

Vergelijk dan.

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

U maakt zich wijselijk zorgen over waarden uit de database die niet overeenkomen met de oorspronkelijke waarde. Een oplossing, indien acceptabel voor uw zakelijke probleem, is om eventuele nanoseconden in microseconden in uw oorspronkelijke gegevens af te kappen. Ik raad deze aanpak in het algemeen aan.

De java.time klassen bieden een truncatedTo methode. Geef een ChronoUnit door enum object om de granulariteit op te geven. In dit geval is dat ChronoUnit.MICROS .

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

Momenteel zou deze benadering moeten volstaan, aangezien het onwaarschijnlijk is dat u nanoseconden in uw gegevens zult hebben. Reguliere computers hebben tegenwoordig geen hardwareklokken die nanoseconden kunnen vastleggen, voor zover ik weet.

Tellen vanaf tijdperk

Als je het je niet kunt veroorloven om eventuele nanoseconde gegevens te verliezen, gebruik dan een telling vanaf tijdperk.

Ik raad het meestal af om datum-tijd te volgen als een telling vanaf een epoche-referentiedatum. Maar u hebt weinig andere keuzes bij het opslaan van uw op nanoseconden gebaseerde waarden in een database zoals MySQL en Postgres die beperkt is tot op microseconden gebaseerde waarden.

Bewaar paar gehele getallen

In plaats van het extreem grote aantal nanoseconden te gebruiken sinds een tijdperk zoals 1970-01-01T00:00Z, raad ik aan de benadering te volgen die is gevolgd door de interne onderdelen van de Instant klasse:gebruik een paar aantal cijfers.

Bewaar een aantal hele seconden als een geheel getal in uw database. Sla in een tweede kolom als een geheel getal het aantal nanoseconden in de fractionele seconde op.

U kunt deze nummers eenvoudig extraheren/injecteren van/naar een Instant voorwerp. Alleen eenvoudige 64-bits long cijfers zijn betrokken; geen behoefte aan BigDecimal of BigInteger . Ik veronderstel dat je een 32-bits integerkolom kunt gebruiken voor ten minste één van de twee getallen. Maar ik zou kiezen voor 64-bits integer-kolomtypen voor eenvoud en voor directe compatibiliteit met de java.time.Instant klasse' paar longs.

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

…en…

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

Als u chronologisch sorteert, moet u sorteren op meerdere niveaus, eerst sorteren op de hele secondenkolom en vervolgens secundair sorteren op de nanos-fractie-van-secondekolom.




  1. Hoe het totaal gevonden rijen te krijgen zonder rekening te houden met de limiet in PDO?

  2. Hoe een record te krijgen met maximale waarde in MySQL

  3. Kan `mysqlcheck` mij helpen databaseproblemen op te lossen zonder mijn database te beschadigen?

  4. Hoe vraag ik naar alle datums die groter zijn dan een bepaalde datum in SQL Server?