将自定义方法映射器映射到 Mapstruct
Map custom method mapper to Mapstruct
我正在为在我未来的项目中使用 Mapstruct 创建一个 poc。
现在我有一个问题是如何将自定义方法映射到一个特殊目标。
例如我有以下接口映射器:
@Mapper
public interface ItemMapper {
static ItemMapper INSTANCE = Mappers.getMapper(ItemMapper.class);
@Mappings({ @Mapping(source = "number", target = "itemnumber"),
@Mapping(source = "description", target = "description"),
@Mapping(source = "itemClass.name", target = "ic"), @Mapping(source = "optionPart", target = "option"),
@Mapping(source = "plannerCode.code", target = "plannercode"),
@Mapping(source = "plannerCode.name", target = "planner"),
@Mapping(source = "vendor.buyerCode.name", target = "buyer"),
@Mapping(source = "vendor.buyerCode.code", target = "buyerCode"),
@Mapping(source = "vendor.number", target = "vendor"),
@Mapping(source = "vendor.name", target = "vendorName"), @Mapping(source = "pcsItem", target = "pcs"),
@Mapping(source = "specialColourVariant", target = "specialColors"),
@Mapping(source = "qtyBufferGreen", target = "greenLine"),
@Mapping(source = "qtyBufferRed", target = "redine"), @Mapping(source = "leadtime", target = "leadTime"),
@Mapping(source = "qtyStock", target = "stockAC"),
@Mapping(source = "qtyStockSupplier", target = "stockSupplier"),
@Mapping(source = "qtyPurchaseOrder", target = "qtyPo"),
@Mapping(source = "qtyShopOrder", target = "qtySo"),
@Mapping(source = "qtyFirmPlannedOrder", target = "qtyFpo"),
@Mapping(source = "qtyForecast", target = "qtyForecast"),
@Mapping(source = "standardCost", target = "stdCost"),
@Mapping(source = "itemCategory.name", target = "category") })
ItemViewModel itemToDto(Item item);
default String locationToLocationDto(Item item) {
return item.getItemsOnDetailedLocations().iterator().next().getLocation().getLocation();
}
default double locationToBinType(Item item) {
return item.getItemsOnDetailedLocations().iterator().next().getBinType();
}
default double itemToLotsize(Item item) {
double lotSize = 0;
if (item.getLotsize() != null) {
lotSize = item.getLotsize();
} else if (item.getItemsOnDetailedLocations() != null && !item.getItemsOnDetailedLocations().isEmpty()) {
ItemsOnDetailedLocation location = item.getItemsOnDetailedLocations().iterator().next();
lotSize = location.getLotSize();
} else {
lotSize = 0.0;
}
return lotSize;
}
default double stockRails(Item item) {
double value = 0;
for (ItemsOnDetailedLocation detailedLocation : item.getItemsOnDetailedLocations()) {
if (detailedLocation.getId().getSource().equals("RAILS")) {
long lotSize2 = detailedLocation.getLotSize();
long binInStock = detailedLocation.getBinInStock();
if (binInStock != 0) {
value += lotSize2 * (binInStock - 0.5);
}
}
}
return value;
}
}
在代码中您可以看到映射和一些默认方法以及其中的其他映射。我如何在 Mapstruct 映射中使用这些方法,以便 mapstruct 使用这些方法在字段中填充值?
Mapstruct 可以使用类似的结构:
@Mapping(target = "name", expression = "java(user.getName() != null " +
" ? user.getName() : "DefaultName")")
表达式 可以包含 java 上的任何结构
例如
item.getItemsOnDetailedLocations()
.iterator().next().getLocation().getLocation();
如果方法比较大,那么值得把它带到另一个服务上,这样调用
因为你有多个默认方法 return 相同的类型。您需要使用 Mapping method selection based on qualifiers.
这意味着您需要按照以下格式编写映射器:
@Mapper
public interface ItemMapper {
// Omitting other mappings for clarity
@Mapping(source = "item", target = "locationDto", qualifiedByName = "locationDto")
@Mapping(source = "item", target = "binType", qualifiedByName = "binType")
@Mapping(source = "item", target = "lotSize", qualifiedByName = "lotSize")
@Mapping(source = "item", target = "stockRails", qualifiedByName = "stockRails")
ItemViewModel itemToDto(Item item);
@Named("locationDto")
default String locationToLocationDto(Item item) {
//Omitting implementation
}
@Named("binType")
default double locationToBinType(Item item) {
//Omitting implementation
}
@Named("lotSize")
default double itemToLotsize(Item item) {
//Omitting implementation
}
@Named("stockRails")
default double stockRails(Item item) {
//Omitting implementation
}
}
一些重要说明:
- 您需要使用 MapStruct 包中的
@Named
- 在
source
中还可以指定方法的参数名称
- 在
qualifiedByName
中您需要指定您在@Named
中写入的值
我强烈建议不要对如此复杂的事情使用表达式。正确更难,维护更难
您可以像下面这样简单地使用它们
@Mapping( target="/*Enter targetFieldName*/", expression="java( /default method which calculates target field/" )
最简单的方法是使用强大的 mapstruct @AfterMapping annotation。例如
@AfterMapping
public void treatAdditional(User user, @MappingTarget StudentSkillsTo studentSkillsTo) {
System.out.println("After mapping!");
}
我正在为在我未来的项目中使用 Mapstruct 创建一个 poc。
现在我有一个问题是如何将自定义方法映射到一个特殊目标。
例如我有以下接口映射器:
@Mapper
public interface ItemMapper {
static ItemMapper INSTANCE = Mappers.getMapper(ItemMapper.class);
@Mappings({ @Mapping(source = "number", target = "itemnumber"),
@Mapping(source = "description", target = "description"),
@Mapping(source = "itemClass.name", target = "ic"), @Mapping(source = "optionPart", target = "option"),
@Mapping(source = "plannerCode.code", target = "plannercode"),
@Mapping(source = "plannerCode.name", target = "planner"),
@Mapping(source = "vendor.buyerCode.name", target = "buyer"),
@Mapping(source = "vendor.buyerCode.code", target = "buyerCode"),
@Mapping(source = "vendor.number", target = "vendor"),
@Mapping(source = "vendor.name", target = "vendorName"), @Mapping(source = "pcsItem", target = "pcs"),
@Mapping(source = "specialColourVariant", target = "specialColors"),
@Mapping(source = "qtyBufferGreen", target = "greenLine"),
@Mapping(source = "qtyBufferRed", target = "redine"), @Mapping(source = "leadtime", target = "leadTime"),
@Mapping(source = "qtyStock", target = "stockAC"),
@Mapping(source = "qtyStockSupplier", target = "stockSupplier"),
@Mapping(source = "qtyPurchaseOrder", target = "qtyPo"),
@Mapping(source = "qtyShopOrder", target = "qtySo"),
@Mapping(source = "qtyFirmPlannedOrder", target = "qtyFpo"),
@Mapping(source = "qtyForecast", target = "qtyForecast"),
@Mapping(source = "standardCost", target = "stdCost"),
@Mapping(source = "itemCategory.name", target = "category") })
ItemViewModel itemToDto(Item item);
default String locationToLocationDto(Item item) {
return item.getItemsOnDetailedLocations().iterator().next().getLocation().getLocation();
}
default double locationToBinType(Item item) {
return item.getItemsOnDetailedLocations().iterator().next().getBinType();
}
default double itemToLotsize(Item item) {
double lotSize = 0;
if (item.getLotsize() != null) {
lotSize = item.getLotsize();
} else if (item.getItemsOnDetailedLocations() != null && !item.getItemsOnDetailedLocations().isEmpty()) {
ItemsOnDetailedLocation location = item.getItemsOnDetailedLocations().iterator().next();
lotSize = location.getLotSize();
} else {
lotSize = 0.0;
}
return lotSize;
}
default double stockRails(Item item) {
double value = 0;
for (ItemsOnDetailedLocation detailedLocation : item.getItemsOnDetailedLocations()) {
if (detailedLocation.getId().getSource().equals("RAILS")) {
long lotSize2 = detailedLocation.getLotSize();
long binInStock = detailedLocation.getBinInStock();
if (binInStock != 0) {
value += lotSize2 * (binInStock - 0.5);
}
}
}
return value;
}
}
在代码中您可以看到映射和一些默认方法以及其中的其他映射。我如何在 Mapstruct 映射中使用这些方法,以便 mapstruct 使用这些方法在字段中填充值?
Mapstruct 可以使用类似的结构:
@Mapping(target = "name", expression = "java(user.getName() != null " +
" ? user.getName() : "DefaultName")")
表达式 可以包含 java 上的任何结构 例如
item.getItemsOnDetailedLocations()
.iterator().next().getLocation().getLocation();
如果方法比较大,那么值得把它带到另一个服务上,这样调用
因为你有多个默认方法 return 相同的类型。您需要使用 Mapping method selection based on qualifiers.
这意味着您需要按照以下格式编写映射器:
@Mapper
public interface ItemMapper {
// Omitting other mappings for clarity
@Mapping(source = "item", target = "locationDto", qualifiedByName = "locationDto")
@Mapping(source = "item", target = "binType", qualifiedByName = "binType")
@Mapping(source = "item", target = "lotSize", qualifiedByName = "lotSize")
@Mapping(source = "item", target = "stockRails", qualifiedByName = "stockRails")
ItemViewModel itemToDto(Item item);
@Named("locationDto")
default String locationToLocationDto(Item item) {
//Omitting implementation
}
@Named("binType")
default double locationToBinType(Item item) {
//Omitting implementation
}
@Named("lotSize")
default double itemToLotsize(Item item) {
//Omitting implementation
}
@Named("stockRails")
default double stockRails(Item item) {
//Omitting implementation
}
}
一些重要说明:
- 您需要使用 MapStruct 包中的
@Named
- 在
source
中还可以指定方法的参数名称 - 在
qualifiedByName
中您需要指定您在@Named
中写入的值
我强烈建议不要对如此复杂的事情使用表达式。正确更难,维护更难
您可以像下面这样简单地使用它们
@Mapping( target="/*Enter targetFieldName*/", expression="java( /default method which calculates target field/" )
最简单的方法是使用强大的 mapstruct @AfterMapping annotation。例如
@AfterMapping
public void treatAdditional(User user, @MappingTarget StudentSkillsTo studentSkillsTo) {
System.out.println("After mapping!");
}