ZonedDateTime MongoDB
ZonedDateTime with MongoDB
正在尝试将 ZonedDateTime
与 MongoDB
一起使用。我可以将 ZonedDateTime
保存在 MongoDB
中,但是当我查看记录时,里面有很多不必要的东西:
> "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
时没有遇到这个问题。
第一个问题是我们可以在某个地方更改一些设置,这些设置只会在 ISODate
和 ZonedDateTime
之间持续存在吗?
第二个问题,mongodb
有没有类似Jsr310JpaConverters
的东西?
更新:
参考以下问卷我创建了自定义转换器并注册了它们,但是问题仍然存在。
Spring Data MongoDB with Java 8 LocalDate MappingException
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);
}
看起来 Spring 支持除 ZonedDateTime
转换器之外的所有 java 时间转换器。您可以通过以下方式注册一个。
@Bean
public CustomConversions customConversions(){
List<Converter<?,?>> converters = new ArrayList<>();
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);
另一种选择是实施自定义编解码器以帮助进行转换。我在 Filtering YearMonth from Mongo 文档中为 YearMonth 创建了一个。如果 reader 他们想为 Zoned Date Time 创建自定义编解码器,我会将其留作练习。
您可以将以下库用于基于编解码器的方法。
在花了太多时间调试之后,我终于找到了最新版本 spring 引导/spring 数据的有效解决方案。这目前正在 Spring Boot 2.0.0.M7 上为我工作。
根据 veeram 接受的答案,我得到了 Couldn't find PersistentEntity for type
我希望这有助于避免掉入兔子洞。
@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());
}
}
}
正在尝试将 ZonedDateTime
与 MongoDB
一起使用。我可以将 ZonedDateTime
保存在 MongoDB
中,但是当我查看记录时,里面有很多不必要的东西:
> "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
时没有遇到这个问题。
第一个问题是我们可以在某个地方更改一些设置,这些设置只会在 ISODate
和 ZonedDateTime
之间持续存在吗?
第二个问题,mongodb
有没有类似Jsr310JpaConverters
的东西?
更新: 参考以下问卷我创建了自定义转换器并注册了它们,但是问题仍然存在。 Spring Data MongoDB with Java 8 LocalDate MappingException
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);
}
看起来 Spring 支持除 ZonedDateTime
转换器之外的所有 java 时间转换器。您可以通过以下方式注册一个。
@Bean
public CustomConversions customConversions(){
List<Converter<?,?>> converters = new ArrayList<>();
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);
另一种选择是实施自定义编解码器以帮助进行转换。我在 Filtering YearMonth from Mongo 文档中为 YearMonth 创建了一个。如果 reader 他们想为 Zoned Date Time 创建自定义编解码器,我会将其留作练习。
您可以将以下库用于基于编解码器的方法。
在花了太多时间调试之后,我终于找到了最新版本 spring 引导/spring 数据的有效解决方案。这目前正在 Spring Boot 2.0.0.M7 上为我工作。
根据 veeram 接受的答案,我得到了 Couldn't find PersistentEntity for type
我希望这有助于避免掉入兔子洞。
@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());
}
}
}