【问题标题】:Map Nested elements - Mapstruct映射嵌套元素 - 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);
        }
    

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

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

【问题讨论】:

    标签: java spring-boot nested-lists mapstruct object-object-mapping


    【解决方案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 的好处是目标类可以是不可变的。

      【讨论】:

        猜你喜欢
        • 2023-03-29
        • 1970-01-01
        • 2018-09-15
        • 2019-07-13
        • 1970-01-01
        • 2016-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多