Je crée un poc pour utiliser Mapstruct dans mes projets futurs.
Maintenant, j'ai une question: comment mapper des méthodes personnalisées sur une cible particulière.
Par exemple, j'ai l'interface suivante mappeur:
@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;
}
}
Dans le code, vous pouvez voir le mappage et certaines méthodes par défaut avec d'autres mappages. Comment puis-je utiliser ces méthodes dans les mappages Mapstruct afin que mapstruct les utilise pour renseigner des valeurs dans les champs?
Comme vous avez plusieurs méthodes par défaut qui retournent le même type. Vous devrez utiliser La sélection de la méthode de mappage en fonction des qualificateurs .
Cela signifie que vous devez écrire votre mappeur au format suivant:
@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
}
}
Quelques notes importantes:
@Named
à partir du package MapStructsource
, vous pouvez également spécifier le nom du paramètre de la méthode.qualifiedByName
, vous devez spécifier la valeur que vous avez écrite dans @Named
Je déconseille fortement d'utiliser des expressions pour des choses aussi compliquées. Il est beaucoup plus difficile de le faire correctement et plus difficile de maintenir
Mapstruct peut utiliser des constructions similaires:
@Mapping(target = "name", expression = "Java(user.getName() != null " +
" ? user.getName() : "DefaultName")")
une expression peut inclure n'importe quelle construction sur Java e.g
item.getItemsOnDetailedLocations()
.iterator().next().getLocation().getLocation();
si la méthode est volumineuse, cela vaut la peine d’utiliser un autre service et d’appeler de cette façon
Vous pouvez simplement les utiliser comme suit
@Mapping( target="/*Enter targetFieldName*/", expression="Java( /default method which calculates target field/" )