映射嵌套元素 - Mapstruct

Posted

技术标签:

【中文标题】映射嵌套元素 - Mapstruct【英文标题】:Map Nested elements - Mapstruct 【发布时间】:2020-11-16 01:26:33 【问题描述】:

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

目标类:

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);
        
    

有人可以帮忙填写上面的评论部分吗? 或者有没有其他选项来映射这些对象?

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

【问题讨论】:

【参考方案1】:

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

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

@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

【讨论】:

我试过这个。它映射“客户映射用户(用户用户)”但“列表映射用户(列表用户)”->此映射现在不起作用。即,我是这样的 -> "user": [ "productDetails": [] , "productDetails": [] , ], 实现从: 1. public List mapUser(List users) ....... List list = new ArrayList(users.size ()); for(用户用户:用户)list.add(mapUser(用户));上面的实现改为 for (User user : users) list.add(userToCustomer(user));并且 userToCustomer 方法没有用户的任何设置器 不...您必须在 mapUser 方法中使用传递 ProductList,以便它进入上下文。尝试以下操作: list.add() 中的 mapUser(user, productList) 如果我们修改像Customer mapUser(User user, @Context ProductList productList),那么List mapUser(List user);不会工作。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

不用@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);

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

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

【讨论】:

以上是关于映射嵌套元素 - Mapstruct的主要内容,如果未能解决你的问题,请参考以下文章

我需要取消嵌套 JSON 数组元素并确保与“ID”列正确映射

Mybatis resultMap 嵌套集合

如何使用 Spark SQL 在 Parquet 文件中选择嵌套数组和映射

MyBatis基础入门《十五》ResultMap子元素(collection)

如何使用 AutoMapper 使用 EntityFramework 使用嵌套列表更新对象?

Flutter:如何将元素添加到 Firebase 数据库中的映射字段?