如何使用 MapStrcut 转换双向链接

问题描述 投票:0回答:1

下面是一个非常简化的汽车共享模型,其中一个

Car
可能被多个
User
使用。我需要将服务对象转换为 DTO 对象,反之亦然:

@Data
public class Car {

    private String brand;
    private String model;
    private List<CarUser> users = new ArrayList<>();

    public void linkUser(CarUser user) {
        this.users.add(user);
        user.setCar(this);
    }
}

@Data
public class CarUser {

    private String name;
    private Car car;
}

@Data
public class CarDTO {

    private String brand;
    private String model;
    private List<CarUserDTO> users = new ArrayList<>();

    public void linkUser(CarUserDTO user) {
        this.users.add(user);
        user.setCar(this);
    }
}

@Data
public class CarUserDTO {

    private String name;
    private CarDTO car;
}

@Mapper
public interface UserConverter {

    CarUser convert(final CarUserDTO user);
    CarUserDTO convert(final CarUser user);
}


@Mapper(uses = UserConverter.class)
public interface CarConverter {

    Car convert(final CarDTO car);
    CarDTO convert(final Car car);
}

方法

linkUser
创建双向链接,即将给定
User
关联到当前
Car
,并将当前
Car
关联到给定
User
。上面代码片段中
Mapper
的问题在于,类
car
/
User
中的
UserDTO
属性永远不会被设置,因为转换器当然不会调用
linkUser
。有什么办法可以设置该属性吗?这里棘手的部分是要设置的
Car
实际上是正在转换的实例。任何帮助将非常感激:-)

java mapstruct
1个回答
0
投票

您可以简单地在 @AfterMapping

 中定义一个 
CarConverter
 方法。重点是克隆已转换用户的列表并将 
users
属性设置为空列表,因为调用
linkUser
方法时将重新填充用户列表。

@Mapper(uses = UserConverter.class)
public interface CarConverter {

  Car convert(final CarDTO car);
  CarDTO convert(final Car car);

  @AfterMapping
  default void linkUsersDTO(Car source, @MappingTarget CarDTO target) {
    List<CarUserDTO> users = new ArrayList<>(target.getUsers());
    target.setUsers(new ArrayList<>());
    users.forEach(target::linkUser);
  }

  @AfterMapping
  default void linkUsers(CarDTO source, @MappingTarget Car target) {
    List<CarUser> users = new ArrayList<>(target.getUsers());
    target.setUsers(new ArrayList<>());
    users.forEach(target::linkUser);
  }

}

此外,由于用户的

car
属性是在
@AfterMapping
方法中设置的,因此无需在
UserConverter::convert
中映射它。

@Mapper
public interface UserConverter {

  @Mapping(target= "car",ignore = true)
  CarUser convert(final CarUserDTO user);

  @Mapping(target= "car",ignore = true)
  CarUserDTO convert(final CarUser user);

}

如果不忽略,则会抛出

StackOverflowError
异常,因为
UserConverter
生成的方法形成循环依赖。

© www.soinside.com 2019 - 2024. All rights reserved.