我试图坚持以下文件:
class Document {
...
private Map data;
...
}
要存储日期,我使用的是Joda的DateTime对象:
data.put("date", DateTime.now());
我正在使用MongoRepository来保存数据。写得很好,我可以看到mongoDB有一个日期类型。
但是,当我读取数据时,我的地图不包含DateTime,而是Date对象。
我明白了,没有什么可以告诉Spring将正在读取的对象的类型从Date(默认)更改为DateTime,因为我没有阅读具体类型。
有没有办法让MongoTemplate / MongoRepository在读取时始终将java.util.Date转换为Joda DateTime?
这可能与转换器有关,但我无法找到如何执行此操作的示例。
感谢。 -AP _
答案 0 :(得分:2)
所以,最后我不得不做出一点妥协。由于我使用Map来保存任意数据,因此无法调用转换器,因为任何东西都可以设置为Object,因此Spring Data不需要进行从Date到DateTime的任何转换。 / p>
我没有使用通用Map,而是创建了我自己的类型,它只是从Map扩展而来:
public class EventData extends HashMap<String, Object> {
...
}
然后,我将我的父类更改为使用EventData而不是Map:
public class Event implements Serializable {
private final EventData
data;
...
}
现在,有了EventData,我可以创建一个自定义映射器:
@ReadingConverter
public class ConsumerHandlerEventDataReadConverter implements Converter<DBObject, EventData> {
@Resource
private MappingMongoConverter
mappingMongoConverter;
@Override
public EventData convert(final DBObject source) {
//First, use the general mapping mongo converter to read the source as it would normally be read
//
final EventData
eventData =
mappingMongoConverter
.read(
EventData.class,
source
);
//Now replaces all occurances of Date in EventData with DateTime
//
for (final Map.Entry<String, Object> entry : eventData.entrySet()) {
//Get the value of this entry
//
final Object
entryValue =
entry
.getValue();
//If it's a date, replace with Datetime
//
if (entryValue instanceof Date) {
entry
.setValue(
new DateTime(
entryValue
)
);
}
}
//Return result
//
return
eventData;
}
}
大多数映射都是由标准映射器完成的,所以我只是连接了一个“不同的”MappingMongoConverter并使用它的read方法来读取数据。然后,我查找所有Date对象并用DateTime替换它们。
要将我的转换器添加到Mongo,我使用MappingMongoConverter注册自定义转换类型:
@Configuration
public class ConsumerHandlerMongoDBConfiguration {
...
@Bean
public CustomConversions customConversions() {
return
new CustomConversions(
Arrays.asList(
consumerHandlerEventDataReadConverter()
)
);
}
@Bean
@Description("Mapping mongo converter for the event")
public MappingMongoConverter consumerProcessHandlerMappingMongoConverter() {
final MappingMongoConverter
converter =
new MappingMongoConverter(
mongoDBConfiguration.dbRefResolver(),
mongoDBConfiguration.mongoMappingContext()
);
converter
.setTypeMapper(
mongoDBConfiguration.mongoTypeMapper()
);
converter
.setCustomConversions(
customConversions()
);
return
converter;
}
...
}
理想情况下,我希望以某种方式创建一个映射器,MappingMongoConverter在处理Date类型时不会特别在EventData的上下文中总是可以参考,但是,查看Spring Data中的readMap(...)代码,我看到了这不会发生:
private Object getPotentiallyConvertedSimpleRead(Object value, Class<?> target) {
if (value == null || target == null || target.isAssignableFrom(value.getClass())) {
return value;
}
if (conversions.hasCustomReadTarget(value.getClass(), target)) {
return conversionService.convert(value, target);
}
if (Enum.class.isAssignableFrom(target)) {
return Enum.valueOf((Class<Enum>) target, value.toString());
}
return conversionService.convert(value, target);
}
如果target.isAssignableFrom(value.getClass()),上面的代码将不会调用任何映射器,并且因为所有内容都可以分配给Object,所以无论如何都无法注册自定义映射器。代码中的下一个语句确实检查了是否转换了.hasCustomReadTarget,但我们从来没有达到它。
无论如何,对于那些试图与转换器做类似事情的人来说,下次也要记录下来。
-AP _
答案 1 :(得分:0)
您必须实现自己的转换器,然后在启用MongoDB存储库(customConversions()
)的类中覆盖@EnableMongoRepositories
。
它还取决于您使用的 Spring Data 版本;到目前为止,我记得还有DateTimeConverters
。
类似于this,但实现了Spring的Converter<T, K>
界面。