복붙노트

[SPRING] MongoDB와의 ZonedDateTime

SPRING

MongoDB와의 ZonedDateTime

MongoDB와 함께 ZonedDateTime을 사용하려고합니다. 나는 MongoDB에 ZonedDateTime을 저장할 수 있지만 레코드를 보면 거기에 너무 많은 불필요한 것들이있다 :

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

또한이 동일한 날짜를 검색하려고하면 다음과 같이 표시됩니다.

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

LocalDateTime으로 작업 할 때이 문제가 발생하지 않았습니다. 첫 번째 질문은 ZonedDateTime을 사용하여 ISODate 만 유지할 수있는 일부 설정을 변경할 수 있습니까? 두 번째 질문은 mongodb 용 Jsr310JpaConverters와 같은 것입니까?

최신 정보: 다음 질문을 참고하면 사용자 지정 변환기를 만들고 등록했지만 문제는 계속 발생합니다. Java 8 LocalDate MappingException을 사용하는 Spring 데이터 MongoDB

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

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

그들을 다음과 같이 등록 함 :

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

해결법

  1. ==============================

    1.Spring이 모든 Java 시간 변환기에서 구역화 된 날짜 시간 변환기를 뺀 것을 지원하는 것처럼 보입니다. 다음과 같이 등록 할 수 있습니다.

    Spring이 모든 Java 시간 변환기에서 구역화 된 날짜 시간 변환기를 뺀 것을 지원하는 것처럼 보입니다. 다음과 같이 등록 할 수 있습니다.

    @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());
           }
       }
    

    다른 대안으로는 ZonedDateTime을 사용하여 MongoDB를 유지하면서 날짜를 변경하는 것입니다. 가져 오는 동안 날짜를 다시 존 날짜 시간으로 다시 변경할 수 있습니다.

    다음은 전환을 돕는 관련 방법입니다.

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

    ZonedDateTime에서 java 유틸리티 날짜.

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

    날짜에서 ZonedDateTime까지

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

    다른 대안은 변환을 돕기 위해 사용자 정의 코덱을 구현하는 것입니다. Mongo 문서에서 YearMonth 필터링에서 YearMonth를 만들었습니다. Zoned Date Time에 대한 사용자 지정 코덱을 만들려면 독자에게 연습 문제로 남겨 두겠습니다.

    코덱 기반의 접근을 위해 아래의 라이브러리를 사용할 수 있습니다.

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

  2. ==============================

    2.이것을 디버깅하는 데 너무 많은 시간을 소비 한 후, 마침내 스프링 부트 / 스프링 데이터의 최신 버전을위한 작업 솔루션을 찾았습니다. 이것은 현재 Spring Boot 2.0.0.M7에서 나를 위해 일하고있다.

    이것을 디버깅하는 데 너무 많은 시간을 소비 한 후, 마침내 스프링 부트 / 스프링 데이터의 최신 버전을위한 작업 솔루션을 찾았습니다. 이것은 현재 Spring Boot 2.0.0.M7에서 나를 위해 일하고있다.

    veeram에서 대답을 받아 들였고, 타입에 PersistentEntity를 찾을 수 없었습니다.

    나는 이것이 누군가 토끼가 무너지는 것을 피하는 데 도움이되기를 바랍니다.

    @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());
            }
        }
    }
    
  3. from https://stackoverflow.com/questions/41127665/zoneddatetime-with-mongodb by cc-by-sa and MIT license