web-dev-qa-db-fra.com

ZonedDateTime avec MongoDB

Essayer d'utiliser ZonedDateTime avec MongoDB. Je peux enregistrer ZonedDateTime dans MongoDB mais quand je regarde l'enregistrement, il y a tellement de choses inutiles là-dedans:

> "timestamp" : {
>             "dateTime" : ISODate("2016-12-13T13:45:53.991Z"),
>             "offset" : {
>                 "_id" : "-05:00",
>                 "totalSeconds" : -18000
>             },
>             "zone" : {
>                 "_class" : "Java.time.ZoneRegion",
>                 "_id" : "America/New_York",
>                 "rules" : {
>                     "standardTransitions" : [ 
>                         NumberLong(-2717650800)
>                     ],
>                     "standardOffsets" : [ 
>                         {
>                             "_id" : "-04:56:02",
>                             "totalSeconds" : -17762
>                         }, 
>                         {
>                             "_id" : "-05:00",
>                             "totalSeconds" : -18000
>                         }
>                     ],
>                     "savingsInstantTransitions" : [ 
>                         NumberLong(-2717650800), 
>                         NumberLong(-1633280400), 
>                         NumberLong(-1615140000), 
>                         NumberLong(-1601830800), 
>                         NumberLong(-1583690400), 
>                         NumberLong(-1570381200),
> and so on....

Aussi quand j'essaye de récupérer cette même date, ça me donne ce qui suit:

> org.springframework.data.mapping.model.MappingException: No property
> null found on entity class Java.time.ZonedDateTime to bind constructor
> parameter to!

Je n'ai pas eu ce problème en travaillant avec LocalDateTime. La première question est de savoir si nous pouvons modifier certains paramètres quelque part qui ne persisteront que ISODate avec ZonedDateTime? Deuxième question, existe-t-il quelque chose comme Jsr310JpaConverters pour mongodb?

MISE À JOUR: En faisant référence au questionnaire suivant, j'ai créé des convertisseurs personnalisés et les ai enregistrés, cependant, le problème persiste. Spring Data MongoDB avec Java 8 LocalDate MappingException

public class ZonedDateTimeToLocalDateTimeConverter implements Converter<ZonedDateTime, LocalDateTime> {
    @Override
    public LocalDateTime convert(ZonedDateTime source) {
        return source == null ? null : LocalDateTime.ofInstant(source.toInstant(), ZoneId
                .systemDefault());
    }
}

Et

public class LocalDateTimeToZonedDateTimeConverter implements Converter<LocalDateTime,
        ZonedDateTime> {
    @Override
    public ZonedDateTime convert(LocalDateTime source) {
        return source == null ? null : ZonedDateTime.of(source, ZoneId.systemDefault());
    }
}

Les a enregistrés comme suit:

@Bean
public CustomConversions customConversions(){
        List<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();
        converters.add(new ZonedDateTimeToLocalDateTimeConverter());
        converters.add(new LocalDateTimeToZonedDateTimeConverter());
        return new CustomConversions(converters);
    }

@Bean
public MongoTemplate getMongoTemplate() throws UnknownHostException {
        MappingMongoConverter converter = new MappingMongoConverter(
                new DefaultDbRefResolver(getMongoDbFactory()), new MongoMappingContext());
        converter.setCustomConversions(customConversions());
        converter.afterPropertiesSet();
        return new MongoTemplate(getMongoDbFactory(), converter);
    }
11
Gurkha

Il semble que Spring prenne en charge tous les convertisseurs de temps Java moins le convertisseur date/heure zoné. Vous pouvez en enregistrer un comme suit.

@Bean
public CustomConversions customConversions(){
    List<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();
    converters.add(new DateToZonedDateTimeConverter());
    converters.add(new ZonedDateTimeToDateConverter());
    return new CustomConversions(converters);
}

@Bean
public MongoTemplate getMongoTemplate() throws UnknownHostException {
    MappingMongoConverter converter = new MappingMongoConverter(
            new DefaultDbRefResolver(getMongoDbFactory()), new MongoMappingContext());
    converter.setCustomConversions(customConversions());
    converter.afterPropertiesSet();
    return new MongoTemplate(getMongoDbFactory(), converter);
}

class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

     @Override
     public ZonedDateTime convert(Date source) {
              return source == null ? null : ofInstant(source.toInstant(), systemDefault());
         }
     }

class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

    @Override
    public Date convert(ZonedDateTime source) {
             return source == null ? null : Date.from(source.toInstant());
       }
   }

Une autre solution alternative serait d'utiliser simplement le ZonedDateTime et de le modifier à ce jour tout en persistant dans MongoDB. Vous pouvez facilement la modifier de la date à la date et à l'heure zonées lors de la récupération.

Voici les méthodes pertinentes pour faciliter les conversions.

ZoneId zoneID = ZoneId.of("America/Chicago");

De ZonedDateTime à Java util date.

Instant instant = Instant.now();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);
Date date = Date.from(zdt.toInstant());

De la date au ZonedDateTime

Instant instant = date.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);

L'autre alternative consiste à implémenter un codec personnalisé pour faciliter les conversions. J'en ai créé un pour YearMonth sur le filtrage YearMonth du document Mongo. Je vais laisser le lecteur s'exercer s'il veut créer un codec personnalisé pour Zoned Date Time.

Vous pouvez utiliser la bibliothèque ci-dessous pour une approche basée sur le codec.

https://github.com/ylemoigne/mongo-jackson-codec

13
user2683814

Après avoir passé beaucoup trop de temps à déboguer cela, j'ai finalement trouvé une solution de travail pour la dernière version des données Spring Boot/Spring. Cela fonctionne actuellement pour moi sur Spring Boot 2.0.0.M7.

Avec la réponse acceptée de veeram, je devenais Couldn't find PersistentEntity for type

J'espère que cela aide quelqu'un à éviter de descendre dans le terrier du lapin.

@Configuration
public class MongoConfiguration {

    @Bean
    public MongoCustomConversions customConversions(){
        List<Converter<?,?>> converters = new ArrayList<>();
        converters.add(DateToZonedDateTimeConverter.INSTANCE);
        converters.add( ZonedDateTimeToDateConverter.INSTANCE);
        return new MongoCustomConversions(converters);
    }

    enum DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

        INSTANCE;

        @Override
        public ZonedDateTime convert(Date source) {
            return ofInstant(source.toInstant(), systemDefault());
        }
    }

    enum ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

        INSTANCE;

        @Override
        public Date convert(ZonedDateTime source) {
            return Date.from(source.toInstant());
        }
    }
}
7
Alex Spence