Description
I had trouble coming up with an issue title that captures the ask here so feel free to edit/suggest
Despite the myriad of customization options in spring-data-mongodb I believe the ask described below is currently not possible even though it'd be desirable :
Motivation
Given the types
class MyModel {
UUID id;
...
}
@Document
class MyDocument {
@Id
String id;
...
}
where MyModel
specifies the entity as it is used in the service tier or any other layer downstream of the components responsible for persistence or schema mapping and MyDocument
defines the storage schema for the MyModel
entity (different primary ID types as an artificially introduced difference that can obviously be mitigated more easily in this case but just to illustrate the point below).
Currently, when using MongoRepository<T, D>
a developer specifies the repository as follows :
interface MyRepository extends MongoRepository<MyDocument, String> {
}
which means that either a repository would have to add default methods to do the mapping and essentially specifiy the repository public API twice :
interface MyRepository extends MongoRepository<MyDocument, String> {
default Optional<MyModel> getModelById(UUID id) {
var conversionService = ...
var documentId = conversionService.convert(id, String.class);
var matchingDocument = findById(documentId);
var model = convert(matchingDocument, MyModel.class);
return model;
}
}
or even more suboptimally, a service with the above repository would inherit the problem of having to convert from the database schema defining type to the service model type :
@Service
class MyService {
MyRepository repository;
ConversionService conversionService; // Assume appropriate converters have been configured
MyModel getModelById(UUID id) {
var documentId = conversionService.convert(id, String.class);
var matchingDocument = repository.findById(documentId).orElse(...);
var model = convert(matchingDocument, MyModel.class);
return model;
}
}
And of course both of the solutions above would scale with the amount of repository or service methods respectively which is exactly why one would want to define this conversion once, and ideally transparently to downstream uses.
I understand it's a subjective discussion on whether or not it's a significant problem to "leak" schema definitions into a service layer and this might very well be one of those "pragmatism over correctness" situations but I'd like to propose adding an option to support the more ideal situation.
Proposal
Allow a developer to configure Spring Data MongoDB such that it will use a different type for the entity/schema mapping than the entity type defined on the repository such that the above could be transformed into :
@EntityMapping(MyDocument.class) // Or some other way to configure this
interface MyRepository extends MongoRepository<MyModel, UUID> {
}
@Service
class MyService {
MyRepository repository;
MyModel getModelById(UUID id) {
return repository.findById(documentId).orElse(...);
}
}
along with some configuration, be it a repository type level annotation (e.g. an optional @EntityMapping(MyDocument.class)
), MongoConfig
level adjustments, adding callbacks, etc.
If this is already possible despite my fiddling and research then I apologize for making anyone read through my novel and I'd much appreciate a pointer in the right direction :) I couldn't get it to work with (my understanding of) the currently available customization options.