【问题标题】:Java 8 Date/Time (JSR-310) types mapping with Spring Data MongoDBJava 8 日期/时间 (JSR-310) 类型与 Spring Data MongoDB 的映射
【发布时间】:2014-07-21 05:46:58
【问题描述】:

我有一个带有 Java 8 日期/时间字段的简单文档

@Document
public class Token {
    private Instant createdAt;
    ...
}

我想坚持使用 Spring Data MongoDB 1.5 版。但是java.time.Instant 类型的字段无法正确反序列化,因为MappingMongoConverter 缺少java.time 类的转换器。

在 Spring 4 中,我发现 org.springframework.format.datetime.standard.DateTimeConverters 具有不同的 Converters,包括声明为私有静态类的 InstantToLongConverterLongToInstantConverter

如何配置 MongoTemplate 以使用它们将 Instant 字段映射到 long?

【问题讨论】:

标签: java java-8 spring-data spring-data-mongodb java-time


【解决方案1】:

@user882209 完美地解释了这一切。
从 Spring Data MongoDB 1.7 开始,添加了对 JSR-310 的支持。
如果应用程序由 Sp​​ring Boot 支持,则超过 1.2.8 的每个版本都将包含它。
在 Spring Boot-ed 应用程序中,您可以执行以下操作:

@Configuration
public class MongoDbConfig {

    @Autowired
    private MongoDbFactory mongoDbFactory;

    @Bean
    public MongoTemplate mongoTemplate() {
        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory),
            new MongoMappingContext());
        converter.setCustomConversions(new CustomConversions(Arrays.asList(...)));

    return new MongoTemplate(mongoDbFactory, converter);
    }
}

Jsr310Converters 类提供以下转换器:
DateToLocalDateTimeConverter - LocalDateTimeToDateConverter DateToLocalDateConverter - LocalDateToDateConverter DateToLocalTimeConverter - LocalTimeToDateConverter DateToInstantConverter - InstantToDateConverter

【讨论】:

  • 如果你从AbstractMongoConfiguration扩展你的配置,你甚至可以不用mongoTemplate bean并且所有可用的转换器都被注册了。
【解决方案2】:

我不知道这是否是最好的方法,但我向 Spring Data MongoDB 1.5.0.RELEASE 添加了 Java 8 日期/时间 (JSR-310) 类型支持,如下所示:

  1. 第一步。添加简单的Spring Converters

    public class InstantToLongConverter implements Converter<Instant, Long> {
        @Override
        public Long convert(Instant instant) {
            return instant.toEpochMilli();
        }
    }
    
    public class LongToInstantConverter implements Converter<Long, Instant> {
        @Override
        public Instant convert(Long source) {
            return Instant.ofEpochMilli(source);
        }
    }
    
    public class LocalDateToStringConverter implements Converter<LocalDate, String> {
        @Override
        public String convert(LocalDate localDate) {
            return localDate.toString();
        }
    }
    
    public class StringToLocalDateConverter implements Converter<String, LocalDate> {
        @Override
        public LocalDate convert(String source) {
            return LocalDate.parse(source);
        }
    }
    
  2. 第二步。在您的 AbstractMongoConfiguration 实现中使用 MappingMongoConverter 注册这些自定义 Converters,如下所示:

    @Configuration
    @EnableMongoRepositories(basePackages = {"my.app.repository"})
    public class MongoConfiguration extends AbstractMongoConfiguration {
    
        ...
    
        @Override
        public CustomConversions customConversions() {
            return new CustomConversions(Arrays.asList(
                    new InstantToLongConverter(), new LongToInstantConverter(),
                    new LocalDateToStringConverter(), new StringToLocalDateConverter()));
        }
    }
    

现在您文档的 Instant 字段将作为长值和 LocalDates 作为字符串持久化。

【讨论】:

  • 我仍然收到 org.springframework.data.mapping.model.MappingException: No property null found on entity class java.time.Instant to bind constructor parameter to!你能检查一下我用你提到的转换器更新的github项目吗?
  • 尝试在Application类中添加@ComponentScan(basePackages = "stackoverflow.java8mongo")注解
  • 但是自从 spring 版本 4.0.1 以来这个转换器已经由 spring 提供。见org.springframework.format.datetime.standard.DateTimeConverters
  • 问题中提到了这些转换器。但截至spring-data-mongodb-1.6.1.RELEASE,它们仍未注册Mongo 类型映射。
  • 顺便说一句。如果您想使用此转换器,请先检查此答案以节省您的工作stackoverflow.com/questions/32507470/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多