MapStruct 反向链接映射可能吗?

MapStruct backlink mapping possible?

我是 MapStruct 的新手,在 google 上找不到我的问题的答案。 我有一个 ShoppingCart,它有样本(以及其他属性),每个样本都需要引用回我的 ShoppingCart。是否可以使用 MapStruct 进行此类映射? 在没有 MapStruct 的情况下,我只是将对 ShoppingCart 的引用传递给示例。这是手写的:

protected ShoppingCart map(Cart cart, DataShareOption dataShareOption) {
//(other stuff)
   for (CartSample cartSample : cart.getCartSamples()) {
       ShoppingCartSample sample = mapCartSample(cartSample, shoppingCart,
       dataShareOption);
       shoppingCart.getSamples().add(sample);
   }
}

protected ShoppingCartSample mapCartSample(CartSample cartSample,
    ShoppingCart shoppingCart, DataShareOption dataShareOption) {

     ShoppingCartSample sample = new ShoppingCartSample();
     sample.setShoppingCart(shoppingCart);
     //(other stuff)
     return sample;
}

// the classes declarations:
// business class
public class ShoppingCart extends ShoppingCartHeader
{
    private List<ShoppingCartSample> samples = new   ArrayList<ShoppingCartSample>();
//rest of the class


// data base class:
@Entity
@Table(name = "cart")
public class Cart extends BaseEntity
{
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "cart")
private Set<CartSample> cartSamples = new HashSet<CartSample>();
   // more stuff here


// business class:
  public class ShoppingCartSample
  {
   private ShoppingCart shoppingCart;
  // rest of the class


// data base class:
@Entity
@Table(name = "cart_sample")
public class CartSample
{
   @ManyToOne()
   @JoinColumn(name = "cart_id")
   private Cart cart;
   // more stuff here

您可以使用 decorator 并使用 toher class 自己设置 link,由 mapstruct

自动调用

你的映射器

@Mapper
@DecoratedWith(MyMapperDecorator.class)
public interface MyMapper {
    ShoppingCart map(Cart cart);
    ShoppingCartSample map(CartSample cart);
}

你的装饰器

public abstract class MyMapperDecorator implements MyMapper {
    private final MyMapper delegate;

    public ParticulierMapperDecorator(MyMapper delegate) {
        this.delegate = delegate;
    }

    public ShoppingCart map(Cart cart){
        ShoppingCart shoppingCart = delegate.map(cart);//map the two objects
        //Set your link
        for(ShoppingCartSample sample: hoppingCart.getSampes()){
            sample.setShoppingCart(shoppingCart)
        }
    }
}

查看 mapstruct-mapping-with-cycles 存储库,它使用新的(从 1.2.0 开始)@Context 映射周期(这是您拥有的)。

代码也在这里:

public class CycleAvoidingMappingContext {
    private Map<Object, Object> knownInstances = new IdentityHashMap<Object, Object>();
    @BeforeMapping
    public <T> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
        return (T) knownInstances.get( source );
    }
    @BeforeMapping
    public void storeMappedInstance(Object source, @MappingTarget Object target) {
        knownInstances.put( source, target );
    }
}

请记住 CycleAvoidingMappingContext 中的 sourcetarget 对象可以是更具体的类型,它们不需要是 Object

映射器看起来像:

@Mapper
public interface MyMapper {
    ShoppingCart map(Cart cart, @Context CycleAvoidingMappingContext context);
    ShoppingCartSample map(CartSample cart, @Context CycleAvoidingMappingContext context);
}

您可以像这样使用 @AfterMapping 注释:

@Mapper
public interface ShoppingCartMapper{
    ShoppingCart map(Cart cart);
    ShoppingCartSample map(CartSample cartSample);

    @AfterMapping
    default void setShoppingCartSampleParent(@MappingTarget ShoppingCart cart){
        for(ShoppingCartSample cartSample : cart.getSamples()){
            cartSample.setShoppingCart(cart);
        }
    }
}