映射嵌套元素 - 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);
我的问题是,我想将 CustProduct 与 Customer 联系起来 为此,我尝试了 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您的@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”列正确映射
如何使用 Spark SQL 在 Parquet 文件中选择嵌套数组和映射
MyBatis基础入门《十五》ResultMap子元素(collection)