java - 在 Spring Data MongoDB 中为 ZonedDateTime 注册一个新的 Date Converter Auditable

标签 java spring-data spring-data-mongodb

我希望我的可审核(@CreatedDate@LastModifiedDate)MongoDB 文档与 ZonedDateTime 字段一起使用。

显然 Spring Data 不支持这种类型(查看 org.springframework.data.auditing.AnnotationAuditingMetadata)。

框架版本:Spring Boot 2.0.0Spring Data MongoDB 2.0.0

Spring Data审计错误:

java.lang.IllegalArgumentException: Invalid date type for member <MEMBER NAME>!
Supported types are [org.joda.time.DateTime, org.joda.time.LocalDateTime, java.util.Date, java.lang.Long, long].

Mongo 配置:

@Configuration
@EnableMongoAuditing
public class MongoConfiguration {

}

可审计实体:

public abstract class BaseDocument {

    @CreatedDate
    private ZonedDateTime createdDate;

    @LastModifiedDate
    private ZonedDateTime lastModifiedDate;

}

我尝试过的事情

我还尝试为 ZonedDateTime 创建自定义转换器,但 Spring Data 不考虑它。 DateConvertingAuditableBeanWrapper 类有一个 ConversionService,它在构造方法中使用 JodaTimeConvertersJsr310ConvertersThreeTenBackPortConverters 配置

自定义转换器:

@Component
public class LocalDateTimeToZonedDateTimeConverter implements Converter<LocalDateTime, ZonedDateTime> {

    @Override
    public ZonedDateTime convert(LocalDateTime source) {
        return source.atZone(ZoneId.systemDefault());
    }

}

Spring Data DateConvertingAuditableBeanWrapper:

class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory {

    abstract static class DateConvertingAuditableBeanWrapper implements AuditableBeanWrapper {

        private final ConversionService conversionService;

    }
}

是否可以审核 ZonedDateTime 字段?

如何注册转换器?

最佳答案

创建一个 DateTimeProvider提供审计时使用的当前时间:

@Component("dateTimeProvider")
public class CustomDateTimeProvider implements DateTimeProvider {
    
    @Override
    public Optional<TemporalAccessor> getNow() {
        return Optional.of(ZonedDateTime.now());
    }
}

然后:

@Configuration
@EnableMongoAuditing(dateTimeProviderRef = "dateTimeProvider")
public class MongoConfiguration {
    
    @Bean
    public MongoCustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new DateToZonedDateTimeConverter());
        converters.add(new ZonedDateTimeToDateConverter());
        return new MongoCustomConversions(converters);
    }

    class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

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

    class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

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

但是,我不会使用 ZonedDateTime以此目的。我会坚持 OffsetDateTime :

OffsetDateTime, ZonedDateTime and Instant all store an instant on the time-line to nanosecond precision. Instant is the simplest, simply representing the instant. OffsetDateTime adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained. ZonedDateTime adds full time-zone rules.

It is intended that ZonedDateTime or Instant is used to model data in simpler applications. This class may be used when modeling date-time concepts in more detail, or when communicating to a database or in a network protocol.

关于java - 在 Spring Data MongoDB 中为 ZonedDateTime 注册一个新的 Date Converter Auditable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43236431/

相关文章:

java - spring-data-rest:是否可以在单个响应中动态嵌入资源的关系?

mongodb - spring data mongodb "id"字段映射

java - 将 JdbcTemplate 与 CrudRepository 混合使用有意义吗?

Mongodb聚合查询对累积值进行减法和分组

java - Spring Boot 1.5.1、Spring Data MongoDB 没有用于存储库的合格 bean

Java 线程在记录器上被阻止

java - 从文本文件输入创建对象

java - 无法为 google 文档运行 google gdata api

java - 如何在详细信息 View 中启动 JFileChooser?

java - 如何使用 "Spring Data JPA"规范进行单元测试方法