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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:52:22  来源:igfitidea点击:

Map custom method mapper to Mapstruct

javamapstruct

提问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 @Namedfrom the MapStruct package
  • In sourceyou can also specify the name of the parameter of the method
  • In qualifiedByNameyou 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!");
}