Mapstruct 'aftermapping' 未调用
Mapstruct 'aftermapping' not called
问题是,根本不会调用用 @AfterMapping
注释的方法。它从 testToEntityMapping
转到 toEntity
方法,但不调用任何 toEntityAfterMapping()
方法。为什么 ?可能吗 ?我怎样才能使用 MapStruct 实现它?
(这里我准备了一个没有意义的场景,但它完全抓住了我问题的本质)
实体:
public class Ford {
private String color;
private String market;
private int totalWidth;
//getters and setters omitted for brevity
}
Dtos:
public abstract class FordDto {
public String market;
public String color;
//getters and setters omitted for brevity
}
public class EuropeanFordDto extends FordDto{
private int totalWidth;
public int getTotalWidth() {
return totalWidth + 2;//"+2" for EU market
}
//setter omitted for brevity
}
public class AmericanFordDto extends FordDto{
private int totalWidth;
public int getTotalWidth() {
return totalWidth + 1;//"+1" for US market
}
//setter omitted for brevity
}
映射器:
public abstract class FordMapper<D extends FordDto> {
public Ford toEntity(D dto) {
/* fill in fields common to both ford versions */
final Ford ford = new Ford();
ford.setColor(dto.getColor());
ford.setMarket(dto.getMarket());
return ford;
}
}
@Mapper(componentModel = "spring")
public abstract class EuropeanFordMapper extends FordMapper<EuropeanFordDto> {
@AfterMapping
public void toEntityAfterMapping(final EuropeanFordDto dto, @MappingTarget final Ford entity) {
/* Fill in fields related to european version of the ford */
entity.setTotalWidth(dto.getTotalWidth());
}
}
@Mapper(componentModel = "spring")
public abstract class AmericanFordMapper extends FordMapper<AmericanFordDto> {
@AfterMapping
public void toEntityAfterMapping(final AmericanFordDto dto, @MappingTarget final Ford entity) {
/* Fill in fields related to american version of the ford */
entity.setTotalWidth(dto.getTotalWidth());
}
}
服务:
@Service
public class CarService {
@Autowired
private AmericanFordMapper americanFordMapper;
@Autowired
private EuropeanFordMapper europeanFordMapper;
public void testToEntityMapping(final FordDto dto) {
if (dto instanceof AmericanFordDto) {
americanFordMapper.toEntity((AmericanFordDto) dto);
} else {
europeanFordMapper.toEntity((EuropeanFordDto) dto);
}
}
}
好的,比我想象的要简单。
public interface FordMapper<D extends FordDto> {
@Mapping(target = "totalWidth", ignore=true)
public abstract Ford toEntity(D dto);
}
你甚至可以查看 toEntity()
方法中的实现,有一个对 toEntityAfterMapping()
的调用,因此一切都是正确的并且符合我们想要的结果。
我对相同问题的解决方案是我忘记将 'default' 关键字添加到我的 @AfterMapping 方法(我使用接口)。在该方法出现在生成的代码中之后。
并且不要忘记 运行 mvn/gradle 进行更改后进行清理和编译。
问题是,根本不会调用用 @AfterMapping
注释的方法。它从 testToEntityMapping
转到 toEntity
方法,但不调用任何 toEntityAfterMapping()
方法。为什么 ?可能吗 ?我怎样才能使用 MapStruct 实现它?
(这里我准备了一个没有意义的场景,但它完全抓住了我问题的本质)
实体:
public class Ford {
private String color;
private String market;
private int totalWidth;
//getters and setters omitted for brevity
}
Dtos:
public abstract class FordDto {
public String market;
public String color;
//getters and setters omitted for brevity
}
public class EuropeanFordDto extends FordDto{
private int totalWidth;
public int getTotalWidth() {
return totalWidth + 2;//"+2" for EU market
}
//setter omitted for brevity
}
public class AmericanFordDto extends FordDto{
private int totalWidth;
public int getTotalWidth() {
return totalWidth + 1;//"+1" for US market
}
//setter omitted for brevity
}
映射器:
public abstract class FordMapper<D extends FordDto> {
public Ford toEntity(D dto) {
/* fill in fields common to both ford versions */
final Ford ford = new Ford();
ford.setColor(dto.getColor());
ford.setMarket(dto.getMarket());
return ford;
}
}
@Mapper(componentModel = "spring")
public abstract class EuropeanFordMapper extends FordMapper<EuropeanFordDto> {
@AfterMapping
public void toEntityAfterMapping(final EuropeanFordDto dto, @MappingTarget final Ford entity) {
/* Fill in fields related to european version of the ford */
entity.setTotalWidth(dto.getTotalWidth());
}
}
@Mapper(componentModel = "spring")
public abstract class AmericanFordMapper extends FordMapper<AmericanFordDto> {
@AfterMapping
public void toEntityAfterMapping(final AmericanFordDto dto, @MappingTarget final Ford entity) {
/* Fill in fields related to american version of the ford */
entity.setTotalWidth(dto.getTotalWidth());
}
}
服务:
@Service
public class CarService {
@Autowired
private AmericanFordMapper americanFordMapper;
@Autowired
private EuropeanFordMapper europeanFordMapper;
public void testToEntityMapping(final FordDto dto) {
if (dto instanceof AmericanFordDto) {
americanFordMapper.toEntity((AmericanFordDto) dto);
} else {
europeanFordMapper.toEntity((EuropeanFordDto) dto);
}
}
}
好的,比我想象的要简单。
public interface FordMapper<D extends FordDto> {
@Mapping(target = "totalWidth", ignore=true)
public abstract Ford toEntity(D dto);
}
你甚至可以查看 toEntity()
方法中的实现,有一个对 toEntityAfterMapping()
的调用,因此一切都是正确的并且符合我们想要的结果。
我对相同问题的解决方案是我忘记将 'default' 关键字添加到我的 @AfterMapping 方法(我使用接口)。在该方法出现在生成的代码中之后。
并且不要忘记 运行 mvn/gradle 进行更改后进行清理和编译。