-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Closed
Labels
Milestone
Description
Use case
Consider the following example mapstruct-jpa-child-parent but with generic JpaContext:
@Data
class ParentDto {
ChildDto child;
}
@Data
class ChildDto {
ParentDto parent;
}
@Data
class ParentEntity {
ChildEntity child;
}
public interface ParentRelation<T> {
void setChildToParent(T parent);
}
@Data
class ChildEntity implements ParentRelation<ParentEntity> {
ParentEntity childToParent;
}
class JpaContext<T> {
T parentEntity;
@BeforeMapping
void setEntity(@MappingTarget T parentEntity) {
this.parentEntity = parentEntity;
}
@AfterMapping
void establishRelation(@MappingTarget ParentRelation<T> childEntity) {
childEntity.setChildToParent(parentEntity);
}
}
interface BaseMapper<T, E> {
default E toEntity(T s) {
return toEntity(s, new JpaContext<>());
}
E toEntity(T s, @Context JpaContext<E> ctx);
}
@Mapper
interface SourceTargetMapper extends BaseMapper<ParentDto, ParentEntity> {
}In this case MapStruct does not invoke @BeforeMapping and @AfterMapping methods in SourceTargetMapperImpl, although it is allowed by Java assignment rules.
Generated Code
Desired generated code:
@Generated(
value = "org.mapstruct.ap.MappingProcessor"
)
class SourceTargetMapperImpl implements SourceTargetMapper {
@Override
public ParentEntity toEntity(ParentDto s, Ctx ctx) {
if ( s == null ) {
return null;
}
ParentEntity parentEntity = new ParentEntity();
ctx.setEntity( parentEntity );
parentEntity.setChild( childDtoToChildEntity( s.getChild(), ctx ) );
return parentEntity;
}
protected ChildEntity childDtoToChildEntity(ChildDto childDto, Ctx ctx) {
if ( childDto == null ) {
return null;
}
ChildEntity childEntity = new ChildEntity();
ctx.establishRelation( childEntity );
return childEntity;
}
}Possible workarounds
Work around of this issue is to create derived class from JpaContext and use extra type parameter in the mapper to supply the derived class. The following example generates exactly the desired Generated Code above.
interface BaseMapper<T, E, C extends JpaContext<E>> {
default E toEntity(T s) {
return toEntity(s, getCtx());
}
E toEntity(T s, @Context C ctx);
C getCtx();
}
@Mapper
interface SourceTargetMapper extends BaseMapper<ParentDto, ParentEntity, SourceTargetMapper.Ctx> {
default Ctx getCtx() {
return new Ctx();
}
class Ctx extends JpaContext<ParentEntity> {
}
}MapStruct Version
1.6.0
Reactions are currently unavailable