所以,最後我不得不做出一點妥協。由於我使用Map來保存任意數據,因此無法調用轉換器,因爲任何對象都可以設置爲Object,因此Spring Data不需要進行從Date到DateTime的任何轉換。
而不是使用一個通用的地圖,我創建了自己的類型,其簡單地從地圖擴展:
public class EventData extends HashMap<String, Object> {
...
}
然後,我改變了使用EVENTDATA我的父類,而不是地圖:
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並使用它的讀取方法來讀取數據。然後,我查找所有Date對象,並用DateTime替換它們。
要我轉換器加到蒙戈,我註冊自定義轉換輸入與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;
}
...
}
理想情況下,我也希望以某種方式創建一個映射與一個Date類型打交道時MappingMongoConverter可以隨時諮詢沒有特別在EventData的上下文中,然而,看着readMap(...在Spring數據)的代碼,我看到這種情況不會發生:
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()),並且因爲一切都可以分配給一個對象,有無論如何,只是無法註冊自定義映射器。代碼中的下一個語句確實檢查了是否轉換.hasCustomReadTarget,但我們從來沒有去過它。
無論如何,下次記錄這一點,以及任何正在嘗試做類似的轉換器的人。
-AP_
爲什麼你使用地圖而不是特定的嵌入類? – chrylis 2015-04-03 20:45:22
我正在通過Jackson讀取數據,並且JSON對象的某些部分已定義好(時間戳,ID,類型),其他部分完全靈活。我需要能夠在MongoDB中讀取和存儲這個對象。最後,我想實現一個「混合」對象,它具有一些定義的字段和一些任意的字段,但還沒有得到這個。所以,我到目前爲止所有的地圖都包含了所有的字段。 – 2015-04-04 03:21:00