Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 强制Spring数据MongoDB将所有日期读取为Joda DateTime类型_Java_Spring_Mongodb_Datetime - Fatal编程技术网

Java 强制Spring数据MongoDB将所有日期读取为Joda DateTime类型

Java 强制Spring数据MongoDB将所有日期读取为Joda DateTime类型,java,spring,mongodb,datetime,Java,Spring,Mongodb,Datetime,我正在尝试保留以下文档: class Document { ... private Map data; ... } 要存储日期,我使用Joda的DateTime对象: data.put("date", DateTime.now()); 我正在使用MongoRepository来保存数据。写作非常有效,我可以看到mongoDB有一个日期类型 但是,当我读取数据时,我的地图不包含DateTime,而是一个Date对象 我明白了,没有什么可以告诉Spring将要读取的对象的

我正在尝试保留以下文档:

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

您必须实现自己的转换器,然后在启用MongoDB存储库的类中重写
customConversions()
@EnableMongoRepositories

它还取决于您使用的Spring数据版本;到目前为止,我还记得还有一个
DateTimeConverters


这就像是,但是实现Spring的
转换器
接口。

因此,最后我不得不做出一些妥协。由于我使用映射来保存任意数据,因此无法调用转换器,因为任何东西都可以设置为对象,因此Spring数据不需要执行从日期到日期时间的任何转换

我没有使用泛型映射,而是创建了自己的类型,它只是从映射扩展而来:

public class EventData extends HashMap<String, Object> {
    ...
}
现在,有了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在处理日期类型时可以始终参考该映射器,而不是专门在EventData的上下文中,但是,查看Spring数据中的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);
}
私有对象getPotentiallyConvertedSimpleRead(对象值,类目标){
if(value==null | | target==null | | target.isAssignableFrom(value.getClass())){
返回值;
}
if(conversions.hasCustomReadTarget(value.getClass(),target)){
返回conversionService.convert(值,目标);
}
if(Enum.class.isAssignableFrom(目标)){
返回Enum.valueOf((类)target,value.toString());
}
返回conversionService.convert(值,目标);
}
如果target.isAssignableFrom(value.getClass()),上面的代码将不会调用任何映射程序,并且由于所有内容都可分配给对象,因此根本无法注册自定义映射程序。代码中的下一条语句确实会检查conversions.hasCustomReadTarget是否正确,但我们始终没有找到它

无论如何,为下一次记录这一点,也为任何试图用转换器做类似事情的人


-AP

为什么要使用映射而不是特定的嵌入式类?我通过Jackson读取数据,虽然JSON对象的某些部分定义良好(时间戳、id、类型),但其他部分完全灵活。我需要能够在MongoDB中读取和存储此对象。最后,我想实现一个“混合”对象,它有一些已定义的字段和一些任意字段,但还没有实现到这一步。到目前为止,我所拥有的只是一张包含所有字段的地图。这是可行的,但并不完全可行。如果EventData包含一个对象,而该对象又包含另一个映射,则该映射中的日期不会转换。此外,由于我在转换器中使用不同的转换器(未配置自定义转换),因此不会应用嵌套转换。如果我使用相同的映射器(已注册转换器),我将进入以堆栈溢出结束的无限循环。所以,我真正想做的只是,不加区别地,将Date的任何实例更改为DateTime。有没有一种方法可以用SpringData实现这一点,而我却找不到?
@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;
    }
    ...
}
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);
}