I'm trying to find a better solution for preventing hibernate proxy initialization when mapping an entity to a response DTO via MapStruct.
I've been converting our codebase to use MapStruct from ModelMapper. If I wanted to accomplish what I'm asking with ModelMapper, I could do something simple like this:
modelMapper
.createTypeMap(Entity.class, DTO.class)
.addMapping(Entity::customGetterMethod, Category::setNormalSetterHere);
That Custom getter method allows me to check if a field has already been fetched from the DB or not to avoid N+1 initializations.
it looks like:
public Set<Entity> customGetterMethod() {
return Hibernate.isInitialized(this.entities) ? this.entities : null;
}
I cannot simply override the normal getter because there are reasonable cases when working with an entity that we would want to allow lazy initialization.
I've tried overriding the default naming strategy to use my own custom getter naming, but since I still need to access normal getters for most basic fields, I couldn't get it to reliably use my customGetter and ignore the default getter when it exists ( and even if I could, its a still seems like a messy solution and difficult to bring teammates up to speed with).
The solution so far has been to use an expression and just copy and modify the generated mapping code for these sorts of fields:
@Mapping(
target = "entities",
expression = "java( mapEntities( source.customGetterMethod(), context ) )")
public abstract ResponseDto toDto(Entity source, @Context CycleAvoidingContext context);
protected Set<ResponseDto> mapEntities(Set<Entity> set, CycleAvoidingContext context) {
/* a copy of the auto-generated code for this mapping essentially */
}
With all the entities and relationships in our projects, this is hardly sustainable since I have to add in an annotated mapping with an expression string for each field along with custom (not custom, just copied) mapping logic. From a maintainability and documentation standpoint, it adds a lot of complexity.
I'm hoping someone can point me to some other mapstruct functionality to accomplish using a custom getter for particular fields in a more streamlined way.