Description
It appears that the collection name is obtained differently in different circumstances:
- When using an interface repository, with the usual methods, or added methods, spring-data-mongodb obtains the collection name from the model class -- either the lower-camel-case name of the class, or whatever is provided in the
@Document
annotation - When using a custom implementation, the collection name is obtained from the
MongoEntityInformation
instance.
In most cases, this effectively results in the same value being obtained. However, this is not always the case. Consider the following situation:
- You have a repository interface called
ItemRepository
that extendsMongoRepository
andItemRepositoryCustom
(below) - You have a custom repository interface called
ItemRepositoryCustom
- You have an implementation for the
ItemRepositoryCustom
interface that also extendsSimpleMongoRepository
- You configure a repository like this:
MongoDatabaseFactory mongoDatabaseFactory = new SimpleMongoClientDatabaseFactory(mongoClient, dbName);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDatabaseFactory);
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate.getConverter().getMappingContext();
MongoPersistentEntity<Item> persistentEntity = (MongoPersistentEntity<Item>) mappingContext.getRequiredPersistentEntity(Item.class);
MappingMongoEntityInformation<Item, String> mongoEntityInformation = new MappingMongoEntityInformation<>(persistentEntity, collectionName);
ItemRepositoryCustomImpl customImpl = new ItemRepositoryCustomImpl(mongoEntityInformation, mongoTemplate);
ItemRepository repository = new MongoRepositoryFactory(mongoTemplate).getRepository(ItemRepository.class, customImpl);
Spring data will get the name from the model class when you use the interface methods, and it will use the value supplied in the MongoEntityInformation
class when you use methods from SimpleMongoRepository
. So, for the same repository, depending on which methods you use, you could operate on two different collection names when working with different methods from the same repository.
The expected behavior would be to get the collection name from the same place, no matter which method is being invoked, particularly when the collection name is customized, as it is in the code snipped above.
I have updated my example project to demonstrate this inconsistent behavior:
https://github.com/Steve973/multiple-mongo-config
When you run the tests, the relevant lines are:
15:48:05.699 [main] DEBUG org.springframework.data.mongodb.core.MongoTemplate - find using query: {} fields: Document{{}} for class: class com.example.multiplemongoconnections.model.Item in collection: coll1
... lines omitted ...
15:48:05.755 [main] DEBUG org.springframework.data.mongodb.core.MongoTemplate - find using query: { "name" : "test item"} fields: Document{{}} for class: class com.example.multiplemongoconnections.model.Item in collection: item
The configured collection name is coll1
, and the model class is Item
. When using a SimpleMongoDatabase
method, it uses the configured value. When using a MongoDatabase
interface extension with a @Query
method, it uses the model class name.
I have not (yet) looked at the code, but, as I understand it, the interface methods are intercepted and queries are made based on the names of the methods, or the content of the query/aggregation in the annotation. In this proxy/aspect, can the instance be examined to determine if there is a custom implementation? If so, then obtain the collection name from the implementation's MongoEntityInformation
property. Else, obtain it from the model class. If whomever triages this ticket agrees that this behavior should be corrected, I can have a look at the code and submit a merge request with these changes. Just let me know.