映射嵌套元素 - Mapstruct

Map Nested elements - Mapstruct

我正在尝试使用 MapStruct 将以下源 classes 映射到目标 class。

目标 类 :

public class Response {
    private List<Customer> customer = new ArrayList<Customer>();
}

public class Customer {
    private String customerId;
    private List<Product> products = new ArrayList<Product>();
}

public class CustProduct {
    private String CustProductId;
    private String CustPdtName;
    private List<productDetail> CustProductDetails = new ArrayList<productDetail>();
}

来源类:

public class UserList {
    protected List<User> user;
}

public class User {
    protected String userId;
    protected List<String> productRefId;  //List of products for that particular user
}

public class ProductList {
    protected List<Product> product;
}
public class Product {
   protected String productId;       //Reference to productRefId
   protected String productName;
   protected List<Details> productDetails;
}
   

映射器接口:

 List<Customer> mapUser(List<User> user);

    @Mappings({
            @Mapping(target = "customerId", source = "userId”),
            @Mapping(target = "products", ignore = true)
    })
    Customer mapUser(User user);

    @Mappings({
        @Mapping(target = "CustProductId", source = "productId"),
        @Mapping(target = "CustPdtName", source = "productName"),
        @Mapping(target = "CustProductDetails", source = "productDetails")
})
CustProduct mapUser(Product product);

我的问题是,我想连接 CustProductCustomer 为此,我尝试了 AfterMapping,例如:

default void findProducts(User user, @MappingTarget Customer customer) {
            List<String> productIds = user.getproductRefId();
            List<CustProduct> custProducts = new ArrayList<>();
            for(int i=0; i<productIds.size();i++){
                    CustProduct custProduct = new CustProduct();
                    custProduct.setCustProductId(productIds.get(i));
                    //Here I want set productName and productDetails to custProduct Object(Iterating through ProductList and get from Product)
                    custProducts.add(custProduct);
                }
            }
            customer.setCustProducts(custProducts);
        }
    

谁能帮忙填一下上面的评论区? 或者是否有任何其他选项来映射这些对象?

已编辑:我尝试了以下解决方案,但接口实现 class 本身发生了变化。

您需要使用 @Context 注释将 ProductList 对象引入上下文。

将映射器方法更改为以下定义并在调用时传递 ProductList 对象 mapUser:

@Mappings({
            @Mapping(target = "customerId", source = "paxJourneyType.paxJourneyID”),
            @Mapping(target = "products", ignore = true)
    })
    Customer mapUser(User user, @Context ProductList productList);

然后您可以在 @AfterMapping 方法中使用相同的 ProductList 对象:

default void findProducts(User user, @Context ProductList productList @MappingTarget Customer customer) {
            List<String> productIds = user.getproductRefId();
            List<CustProduct> custProducts = new ArrayList<>();
            for(int i=0; i<productIds.size();i++){
                    CustProduct custProduct = new CustProduct();
                    custProduct.setCustProductId(productIds.get(i));
                    Product product = getProduct(ProductList productList,productIds.get(i));
                    custProduct.setCustPdtName(product.getProductName);
                    custProducts.add(custProduct);
                }
            }
            customer.setCustProducts(custProducts);
        }

private Product getProduct(ProductList productList,String productId){
    //Iterate through ProductList and get from Product
}

您的@AfterMapping 方法不起作用,因为@MappingTarget 应该是构建器类型

@AfterMapping
default void findProducts(User user, @MappingTarget Customer.CustomerBuilder customer) {
...
}

你可以不使用 @AfterMapping 但你需要稍微帮助一下 MapStruct:

@Mapper
public interface CustMapper {

    @Mapping(target = "customerId", source = "userId")
    @Mapping(target = "products", source = "productRefIds")
    Customer map(User user, @Context Map<String, Product> productsMap);

    List<CustProduct> map(List<String> productRefIds, @Context Map<String, Product> productsMap);

    default CustProduct map(String productId, @Context Map<String, Product> productsMap) {
        return map(productsMap.get(productId));
    }

    @Mapping(target = "custProductId", source = "productId")
    @Mapping(target = "custProductName", source = "productName")
    @Mapping(target = "custProductDetails", source = "productDetails")
    CustProduct map(Product product);

    CustProductDetail map(ProductDetail productDetail);
}

或者,您可以手动迭代 productRefIds

@Mapper
public interface CustMapper {

    @Mapping(target = "customerId", source = "userId")
    @Mapping(target = "products", source = "productRefIds")
    Customer map(User user, @Context Map<String, Product> productsMap);

    default List<CustProduct> map(List<String> productRefIds, @Context Map<String, Product> productsMap) {
        return productRefIds.stream().map(productsMap::get).map(this::map).collect(Collectors.toList());
    }

    @Mapping(target = "custProductId", source = "productId")
    @Mapping(target = "custProductName", source = "productName")
    @Mapping(target = "custProductDetails", source = "productDetails")
    CustProduct map(Product product);

    CustProductDetail map(ProductDetail productDetail);
}

在这两种情况下,当 productsMap 中不存在 productId 时,您需要以某种方式处理这种情况。

不使用 @AfterMapping 的好处是目标 类 可以是不可变的。