您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用Spring Boot> = 2.0.1将ZonedDateTime保存到MongoDB时发生CodecConfigurationException

使用Spring Boot> = 2.0.1将ZonedDateTime保存到MongoDB时发生CodecConfigurationException

像Oliver Drotbohm自己在DATAMONGO-2106中所说的那样,Spring Data MongoDB从未支持使用时区保留日期时间类型。

这些是已知的解决方法

@Component
@WritingConverter
public class zoneddatetimeToDocumentConverter implements Converter<zoneddatetime, Document> {
    static final String DATE_TIME = "dateTime";
    static final String ZONE = "zone";

    @Override
    public Document convert(@Nullable zoneddatetime zoneddatetime) {
        if (zoneddatetime == null) return null;

        Document document = new Document();
        document.put(DATE_TIME, Date.from(zoneddatetime.toInstant()));
        document.put(ZONE, zoneddatetime.getZone().getId());
        document.put("offset", zoneddatetime.getOffset().toString());
        return document;
    }
}

@Component
@ReadingConverter
public class DocumentTozoneddatetimeConverter implements Converter<Document, zoneddatetime> {

    @Override
    public zoneddatetime convert(@Nullable Document document) {
        if (document == null) return null;

        Date dateTime = document.getDate(DATE_TIME);
        String zoneId = document.getString(ZONE);
        ZoneId zone = ZoneId.of(zoneId);

        return zoneddatetime.ofInstant(dateTime.toInstant(), zone);
    }
}

@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.port}")
    private int port;

    @Override
    public MongoClient mongoClient() {
        return new MongoClient(host, port);
    }

    @Override
    protected String getDatabaseName() {
        return database;
    }

    @Bean
    public CustomConversions customConversions() {
        return new MongoCustomConversions(asList(
                new zoneddatetimeToDocumentConverter(),
                new DocumentTozoneddatetimeConverter()
        ));
    }
}
public class zoneddatetimeCodec implements Codec<zoneddatetime> {

    public static final String DATE_TIME = "dateTime";
    public static final String ZONE = "zone";

    @Override
    public void encode(final BsonWriter writer, final zoneddatetime value, final EncoderContext encoderContext) {
        writer.writeStartDocument();
        writer.writeDateTime(DATE_TIME, value.toInstant().getEpochSecond() * 1_000);
        writer.writeString(ZONE, value.getZone().getId());
        writer.writeEndDocument();
    }

    @Override
    public zoneddatetime decode(final BsonReader reader, final DecoderContext decoderContext) {
        reader.readStartDocument();
        long epochSecond = reader.readDateTime(DATE_TIME);
        String zoneId = reader.readString(ZONE);
        reader.readEndDocument();

        return zoneddatetime.ofInstant(Instant.ofEpochSecond(epochSecond / 1_000), ZoneId.of(zoneId));
    }

    @Override
    public Class<zoneddatetime> getEncoderClass() {
        return zoneddatetime.class;
    }
}

@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.port}")
    private int port;

    @Override
    public MongoClient mongoClient() {
        return new MongoClient(host + ":" + port, createOptions());
    }

    private MongoClientOptions createOptions() {
        CodecProvider pojoCodecProvider = PojoCodecProvider.builder()
                .automatic(true)
                .build();

        CodecRegistry registry = CodecRegistries.fromRegistries(
                createCustomCodecRegistry(),
                MongoClient.getDefaultCodecRegistry(),
                CodecRegistries.fromProviders(pojoCodecProvider)
        );

        return MongoClientOptions.builder()
                .codecRegistry(registry)
                .build();
    }

    private CodecRegistry createCustomCodecRegistry() {
        return CodecRegistries.fromCodecs(
                new zoneddatetimeCodec()
        );
    }

    @Override
    protected String getDatabaseName() {
        return database;
    }
}
mongodb 2022/1/1 18:22:28 有337人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶