Java 将自定义方法映射器映射到 Mapstruct
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48521903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Map custom method mapper to Mapstruct
提问by JimmyD
I'm creating a poc for using Mapstruct in my future projects.
我正在创建一个 poc,以便在我未来的项目中使用 Mapstruct。
Now I have one question how to map custom methods to a special target.
现在我有一个问题如何将自定义方法映射到特殊目标。
For example I have following interface mapper:
例如我有以下接口映射器:
@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;
}
}
In the code you can see the mapping and some default methods with other mapping in it. How can I use those methods in the Mapstruct mappings so that mapstruct uses those methods to fillin values in the fields?
在代码中,您可以看到映射和一些带有其他映射的默认方法。如何在 Mapstruct 映射中使用这些方法,以便 mapstruct 使用这些方法来填充字段中的值?
采纳答案by Filip
As you have multiple default methods that return the same type. You would need to use Mapping method selection based on qualifiers.
因为您有多个返回相同类型的默认方法。您需要使用基于 qualifiers 的 Mapping 方法选择。
What this means is that you would need to write your mapper in the following format:
这意味着您需要按以下格式编写映射器:
@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
}
}
Some important notes:
一些重要的注意事项:
- You need to use
@Named
from the MapStruct package - In
source
you can also specify the name of the parameter of the method - In
qualifiedByName
you need to specify the value that you have written in@Named
- 您需要
@Named
从 MapStruct 包中使用 - 在
source
你还可以指定方法的参数名称 - 在
qualifiedByName
您需要指定您已写入的值@Named
I would strongly advise against using expressions for such complicated things. It is much more difficult to get it correct and it is more difficult for maintaining
我强烈建议不要在如此复杂的事情上使用表达式。纠正起来要困难得多,维护起来也困难得多
回答by Redbore
Mapstruct can use similar constructions:
Mapstruct 可以使用类似的结构:
@Mapping(target = "name", expression = "java(user.getName() != null " +
" ? user.getName() : "DefaultName")")
an expressioncan include any constructions on java e.g
一个表达式可以包括java上的任何结构,例如
item.getItemsOnDetailedLocations()
.iterator().next().getLocation().getLocation();
if the method is large, then it is worthwhile to take it to another service and call this way
如果方法很大,那么值得把它带到另一个服务并这样调用
回答by Naveen
You can simply use them like following
您可以简单地使用它们,如下所示
@Mapping( target="/*Enter targetFieldName*/", expression="java( /default method which calculates target field/" )
回答by Grigory Kislin
Simplest way is using powerfull mapstruct @AfterMapping annotation. E.g.
最简单的方法是使用强大的 mapstruct @AfterMapping 注释。例如
@AfterMapping
public void treatAdditional(User user, @MappingTarget StudentSkillsTo studentSkillsTo) {
System.out.println("After mapping!");
}