4

ObjectId によって DB からオブジェクトをフェッチするコンバーターを作成しようとしています。ただし、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 に、ユーザー参照を持つオブジェクトを User オブジェクトとして読み取り、User 値を持つオブジェクトをユーザー参照として書き込む必要があることを理解していますか?

おもう。

  1. データ モデルが不適切です (MongoTemplate で JOIN 操作をエミュレートしようとしています。これは、データ モデルに何かが欠けていることを意味します。これは、mongo を操作する方法ではありません)。
  2. 必要なときに User を明示的に呼び出すだけで、追加の作業で DB を過負荷にしないでください。パフォーマンスに問題が発生します
  3. 必要に応じて、現在のユーザーで強化する別のオブジェクトを使用できます
  4. Hibernate のような SQL と ORM は、あなたにとってより良いアプローチでしょうか?
  5. 目的に合わせて Hibernate OGM を試してみてください。必要な機能が提供される可能性があります (確かではありませんが、それを使用したことはありません)。
于 2015-12-21T02:24:56.787 に答える