java spring spring-data spring-data-mongodb java-time

Almacene Java 8 Instant como fecha BSON utilizando SpringData-MongoDB



spring-data spring-data-mongodb (1)

Tengo la siguiente clase que quiero almacenar en MongoDB usando Spring Data

@Document() public class Tuple2<T extends Enum<T>> { @Id private String id; @Indexed @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private final Instant timeCreated; ... }

DateTimeFormat anotación javadoc estados:

Declara que un campo debe estar formateado como una fecha y hora. Admite el formato por patrón de estilo, patrón de fecha y hora ISO o cadena de patrón de formato personalizado. Se puede aplicar a los tipos de valor java.util.Date, java.util.Calendar, java.long.Long, Joda-Time; y a partir de Spring 4 y JDK 8, también a los tipos JSR-310 java.time.

Estoy usando Spring 4.1.1 y JDK 8, así que espero que se aplique a Instant . Sin embargo, esto es lo que realmente se almacena:

"timeCreated" : { "seconds" : NumberLong(1416757496), "nanos" : 503000000 }

Si escribo y registro el convertidor personalizado de Instant to Date como se explica en esta respuesta, entonces funciona, pero me gustaría evitarlo, ya que estoy seguro de que debe haber una mejor manera.

Después de seguir investigando en el código fuente de Spring, he encontrado la siguiente clase Jsr310DateTimeFormatAnnotationFormatterFactory que parece prometedora:

Formatea los campos anotados con la anotación DateTimeFormat usando el paquete JSR-310 java.time en JDK 8.

Su fuente no hace referencia a Instant , pero sí hace referencia a OffsetTime y LocalTime. Aun así, cuando cambio Instant en ser OffsetDateTime en mi ejemplo, todavía se almacena como un objeto compuesto en lugar de ISODate.

¿Lo que falta?


Creo que el problema es lo que intentas usar Instant como momento. Conceptualmente, es un punto de la línea de tiempo y no implica formato.

Como sabemos, Java 8 time API se desarrolló con un ojo en joda-time (y con la participación de los desarrolladores de joda-time). Aquí está el comentario de Joda-Time Instant :

Se debe utilizar un Instant para representar un punto en el tiempo independientemente de cualquier otro factor, como la cronología o la zona horaria.

Es por eso que no hay posibilidades de formato para org.joda.time.Instant en JodaDateTimeFormatAnnotationFormatterFactory que apareció en Spring desde la versión 3.0. Y tampoco se implementó en Jsr310DateTimeFormatAnnotationFormatterFactory

Por lo tanto, debe usar un convertidor personalizado o considerar usar una clase más adecuada.