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



代码:

@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 定义)更新了代码,但出现了异常:



完全异常(exception):
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,如下所示:

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

和 @Autowire 它在您的配置中。

关注@Savash 更新

我没有足够注意你的配置。

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

作为解决方案:
  • 您可以使用 ApplicationContextAware 创建您的 CustomConversions,并在第一次调用时懒惰地提取 MongoTemplate 引用。
  • 我以为你在使用 CustomConversions 作为 spring-integration 或其他东西的一部分。如果是这样,它不需要成为 Mongo 转换器的一部分。如果你需要它作为 MongoConverters,你正在做一些非常奇怪的事情。

  • 什么是确切的用例,你需要这个吗?

    以下评论:

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

    我认为。
  • 你有一个错误的数据模型(你试图在你的 MongoTemplate 中模拟 JOIN 操作,这意味着你在你的数据模型中遗漏了一些东西,这不是你应该如何使用 mongo)。
  • 只需在需要时显式调用 User,不要用额外的工作使数据库过载,你会遇到性能问题
  • 您可以根据需要使用另一个对象,您将使用当前用户丰富它
  • 也许像 Hibernate 这样的 SQL & ORM 对你来说是更好的方法?
  • 为您的目的尝试 Hibernate OGM,它可能提供您需要的功能(不确定,但尚未使用它)
  • 10-06 14:17