4

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

org.springframework.core.convert.ConversionFailedException:

无法将类型 org.bson.types.ObjectId 转换为类型 com.atlas.mymodule.datadomain.MyObject 以获取值“130000000000000000000013”;

嵌套异常是 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 定义),但出现异常:

创建名为“mongoTemplate”的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?

完全例外:

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?

谢谢。

4

1 回答 1

1

ObjectIdToMyObjectConverter 不是 spring bean。如果您希望 @Autowired 工作,请将 ObjectIdToMyObjectConverter 创建为 Spring bean,如下所示:

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

并在您的配置中 @Autowire 它。

关注@Savash 更新

我对你的配置不够重视。

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

作为解决方案:

  1. 您可以使用 ApplicationContextAware 创建您的 CustomConversions,并在第一次调用时懒惰地提取 MongoTemplate 引用。
  2. 我以为您将 CustomConversions 用作弹簧集成或其他东西的一部分。如果是这样,它不需要成为 Mongo 转换器的一部分。如果你需要它作为 MongoConverters,你正在做一些非常奇怪的事情。

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

以下评论:

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

我认为。

  1. 您的数据模型不好(您试图在 MongoTemplate 中模拟 JOIN 操作,这意味着您的数据模型中缺少某些内容,这不是您应该使用 mongo 的方式)。
  2. 只需在需要时显式调用 User 即可,不要因额外的工作而使数据库超载,否则会出现性能问题
  3. 您可以根据需要使用另一个对象,您将使用当前用户丰富该对象
  4. 也许像 Hibernate 这样的 SQL 和 ORM 对您来说是更好的方法?
  5. 为您的目的尝试 Hibernate OGM,它可能会提供您需要的功能(但不确定,尚未使用它)
于 2015-12-21T02:24:56.787 回答