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
中的 source
和 target
对象可以是更具体的类型,它们不需要是 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);
}
}
}
我是 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
中的 source
和 target
对象可以是更具体的类型,它们不需要是 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);
}
}
}