1. 概述
Spring Data MongoDB模块提高了在 Spring 项目中与 MongoDB 数据库交互时的可读性和可用性。

在本教程中,我们将重点介绍在读取和写入 MongoDB 数据库时如何处理Java的ZonedDateTime对象。

2. 设置
要使用 Spring Data MongoDB 模块,我们需要添加以下依赖项:

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>

可以在[此处](https://search.maven.org/classic/#search|ga|1|g%3A"org.springframework.data" AND a%3A"spring-data-mongodb")找到该库的最新版本。

让我们定义一个名为Action的模型类(具有ZonedDateTime属性):

@Document
public class Action {
@Id
private String id;

private String description;
private ZonedDateTime time;

// constructor, getters and setters
}

为了与 MongoDB 交互,我们还将创建一个扩展 MongoRepository的接口:

public interface ActionRepository extends MongoRepository<Action, String> { }
1
现在我们将定义一个测试,将一个Action对象插入 MongoDB 并断言它以正确的时间存储。在断言评估中,我们将删除纳秒信息,因为 MongoDB Date类型的精度为毫秒:

@Test
public void givenSavedAction_TimeIsRetrievedCorrectly() {
String id = "testId";
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);

actionRepository.save(new Action(id, "click-action", now));
Action savedAction = actionRepository.findById(id).get();

Assert.assertEquals(now.withNano(0), savedAction.getTime().withNano(0));
}

开箱即用,我们在运行测试时会收到以下错误:

org.bson.codecs.configuration.CodecConfigurationException:
Can't find a codec for class java.time.ZonedDateTime
1
2
Spring Data MongoDB 没有定义ZonedDateTime转换器。让我们看看如何配置它们。

3. MongoDB 转换器
我们可以通过定义一个用于从 MongoDB 读取和写入的转换器来处理ZonedDateTime对象(跨所有模型)。

为了便于阅读,我们将Date对象转换为ZonedDateTime对象。在下一个示例中,我们使用ZoneOffset.UTC ,因为Date对象不存储区域信息:

public class ZonedDateTimeReadConverter implements Converter<Date, ZonedDateTime> {
@Override
public ZonedDateTime convert(Date date) {
return date.toInstant().atZone(ZoneOffset.UTC);
}
}

然后,我们将ZonedDateTime对象转换为Date对象。如果需要,我们可以将区域信息添加到另一个字段:

public class ZonedDateTimeWriteConverter implements Converter<ZonedDateTime, Date> {
@Override
public Date convert(ZonedDateTime zonedDateTime) {
return Date.from(zonedDateTime.toInstant());
}
}

创建自己的MongoConfig:

@EnableMongoRepositories(basePackages = { "com.baeldung" })
public class MongoConfig extends AbstractMongoClientConfiguration {

private final List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();

@Override
protected String getDatabaseName() {
return "test";
}

@Override
public MongoCustomConversions customConversions() {
converters.add(new ZonedDateTimeReadConverter());
converters.add(new ZonedDateTimeWriteConverter());
return new MongoCustomConversions(converters);
}

}

使用@EnableMongoRepositories注解来指定开启MongoDB存储库。类似于JPA中的@EnableJpaRepositories。

由于Date对象不存储时区偏移量,因此我们在示例中使用 UTC。将 ZonedDateTimeReadConverter 和 ZonedDateTimeWriteConverter添加到 MongoCustomConversions 后,我们的测试现在将通过。

存储对象的简单打印如下所示:

Action{id='testId', description='click', time=2018-11-08T08:03:11.257Z}

posted on 2023-06-29 10:43  张释文  阅读(109)  评论(0编辑  收藏  举报