如何将mongoTemplate自动连接到自定义类型转换器? [英] How to autowire mongoTemplate into custom type converter?

查看:148
本文介绍了如何将mongoTemplate自动连接到自定义类型转换器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个转换器,该转换器将通过它的ObjectId从DB中获取对象.但是mongoTemplate在转换器中始终为空:

I'm trying to create a converter that will fetch object from DB by it's ObjectId. But the mongoTemplate is always empty in converter:

org.springframework.core.convert.ConversionFailedException:

org.springframework.core.convert.ConversionFailedException:

失败 从org.bson.types.ObjectId类型转换为type com.atlas.mymodule.datadomain.MyObject的价值 '130000000000000000000013';

Failed to convert from type org.bson.types.ObjectId to type com.atlas.mymodule.datadomain.MyObject for value '130000000000000000000013';

嵌套的例外是 java.lang.NullPointerException

nested exception is java.lang.NullPointerException

代码:

@Component
public class ObjectIdToMyObjectConverter implements Converter<ObjectId, MyObject> {

    @Autowired
    private MongoTemplate mongoTemplate; // null ???

    public MyObject convert(ObjectId objectId) {
        return mongoTemplate.findById(objectId, MyObject.class); // <- NullPointerException
    }
}

配置:

@Configuration
@ComponentScan
@EnableMongoRepositories
public abstract class MyModuleConfiguration extends AbstractMongoConfiguration {

    @Override
    public MongoClient mongo() throws Exception {
        List<MongoCredential> mongoCredential = getMongoCredentials();
        return mongoCredential == null ?
            new MongoClient(getMongoServerAddresses()) :
            new MongoClient(getMongoServerAddresses(), mongoCredential, getMongoClientOptions());
    }

    protected abstract List<MongoCredential> getMongoCredentials();

    protected abstract MongoClientOptions getMongoClientOptions();

    protected abstract List<ServerAddress> getMongoServerAddresses() throws UnknownHostException;

    @Bean
    public ObjectIdToMyObjectConverter objectIdToMyObjectConverter() {
        return new ObjectIdToMyObjectConverter());
    }

    @Override
    public CustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
        converters.add(objectIdToMyObjectConverter());

        return new CustomConversions(converters);
    }
}

测试配置:

public class MyModuleTestConfiguration extends MyModuleConfiguration {
  // overrides abstract methods, defines connection details...
}

更新:

我已经根据@mavarazy的建议(添加了ObjectIdToMyObjectConverter bean定义)更新了代码,但出现了异常:

I've updated the code according to @mavarazy suggestion (added ObjectIdToMyObjectConverter bean definition) but got an exception:

创建名称为'mongoTemplate'的bean时出错:请求的bean是 当前正在创建中:是否有无法解决的循环引用?

Error creating bean with name 'mongoTemplate': Requested bean is currently in creation: Is there an unresolvable circular reference?

完全例外:

Error creating bean with name 'mongoTemplate' defined in com.atlas.MyModule.MyModuleTestConfiguration: 
    Bean instantiation via factory method failed;

nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.data.mongodb.core.MongoTemplate]: Factory method 'mongoTemplate' threw exception; 

nested exception is org.springframework.beans.factory.BeanCreationException: 
    Error creating bean with name 'mappingMongoConverter' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed; 

nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.data.mongodb.core.convert.MappingMongoConverter]: Factory method 'mappingMongoConverter' threw exception; 

nested exception is org.springframework.beans.factory.BeanCreationException: 
    Error creating bean with name 'mongoMappingContext' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed;

nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.data.mongodb.core.mapping.MongoMappingContext]: Factory method 'mongoMappingContext' threw exception; 

nested exception is org.springframework.beans.factory.BeanCreationException: 
    Error creating bean with name 'customConversions' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed; 

nested exception is org.springframework.beans.BeanInstantiationException: 
    Failed to instantiate [org.springframework.data.mongodb.core.convert.CustomConversions]: Factory method 'customConversions' threw exception; 

nested exception is org.springframework.beans.factory.BeanCreationException: 
    Error creating bean with name 'objectIdToMyObjectConverter': Injection of autowired dependencies failed; 

nested exception is org.springframework.beans.factory.BeanCreationException: 
    Could not autowire field: private org.springframework.data.mongodb.core.MongoTemplate com.atlas.MyModule.ObjectIdToMyObjectConverter.mongoTemplate; 

nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: 
    Error creating bean with name 'mongoTemplate': Requested bean is currently in creation: Is there an unresolvable circular reference?

谢谢.

推荐答案

ObjectIdToMyObjectConverter不是spring bean.如果您希望@Autowired正常工作,请像下面这样将ObjectIdToMyObjectConverter创建为Spring bean:

ObjectIdToMyObjectConverter is not a spring bean. If you want @Autowired to work, create ObjectIdToMyObjectConverter as Spring bean, like this:

@Bean
public ObjectIdToMyObjectConverter objectIdToMyObjectConverter() {
    return new ObjectIdToMyObjectConverter());
}

并在配置中使用@Autowire.

and @Autowire it in your configuration.

在@Savash更新之后

Following @Savash update

我对您的配置没有足够的重视.

I have not paid enough attention to your configurations.

看到的事情正在发生,因为您试图创建依赖于CustomConversions的MongoTemplate,同时CustomConversions依赖于MongoTemplate,spring不能也不应该这样做.

What you see is happening because you are trying to create MongoTemplate, which depends on CustomConversions, and at the same time CustomConversions depend on MongoTemplate, spring can't and should not do that.

作为解决方案:

  1. 您可以使用ApplicationContextAware创建CustomConversions,并在第一次调用时延迟提取MongoTemplate参考.
  2. 我认为您正在使用CustomConversions作为spring-integration的一部分.如果是这样,它就不必成为Mongo转换器的一部分.如果您需要MongoConverters,那么您所做的事情确实很奇怪.

确切的用例是什么?您需要使用它吗?

What is exact use case, you need this for?

以下评论:

我是否理解正确,您希望MongoTemplate读取带有用户引用的对象作为User对象,并写入带有User值的对象作为用户参考?

Do I understand right, that you want MongoTemplate to read object with user reference as User object, and write object with User value as user reference?

我想.

  1. 您的数据模型不好(您正在尝试在MongoTemplate中模拟JOIN操作,这意味着您在数据模型中缺少某些内容,而这不是您应该使用mongo的方式.)
  2. 只需在需要时显式调用User,不要使DB负担过多的额外工作,您将在性能上遇到问题
  3. 您可以根据需要使用另一个对象,该对象将使当前用户充实
  4. 也许是SQL&像Hibernate这样的ORM对您来说是一种更好的方法?
  5. 尝试使用Hibernate OGM,它可能会提供您需要的功能(虽然不确定,但尚未使用它)

这篇关于如何将mongoTemplate自动连接到自定义类型转换器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆