spring-data-mongodb
spring-data-mongodb copied to clipboard
Different methods of obtaining collection name between interface repositories and custom repositories may produce inconsistent results
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
@Documentannotation - When using a custom implementation, the collection name is obtained from the
MongoEntityInformationinstance.
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
ItemRepositorythat extendsMongoRepositoryandItemRepositoryCustom(below) - You have a custom repository interface called
ItemRepositoryCustom - You have an implementation for the
ItemRepositoryCustominterface 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.
Hello, @christophstrobl I understand that you are very busy, so I hope that tagging you is OK. Is my issue report ok, and is it something that you and your team will consider? I have cloned this repo, and, since I am not familiar with this code base, it would help if someone could point me in the right direction with regard to the packages/classes to look at for repository method invocation. And, please let me know if I can provide better details, or whatever you need.
The issue is scheduled for triage in the team. Please be patient and give us a little time. Thank you!
Ok. Thank you for the update!
Good catch - thanks for reporting! We'll take care of this.
Is there any way that there could be some resolution to this? It has been open for over a year now.