下面是一个非常简化的汽车共享模型,其中一个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的问题在于,类User/UserDTO中的car属性从未设置过,因为转换器当然不会调用linkUser.有什么方法可以设置该属性吗?这里的棘手之处在于,要设置的Car实际上是要转换的实例.如有任何帮助,将不胜感激:-)

推荐答案

您可以简单地在CarConverter中定义一个@AfterMapping方法.重点是克隆转换后的用户列表,并将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生成的方法形成循环依赖.

Java相关问答推荐

Saxon 9:如何从Java扩展函数中的net.sf.saxon.expr. XPathContent中获取声明的变量

空手道比赛条件

Java .类参数不通过构造函数传递

如何使用AWS CLI从S3存储桶中的所有对象中删除用户定义的元数据?

我需要生成一个文件来整合每个特性执行的所有JSON结果

编译多个.Java文件并运行一个依赖于用户参数的文件

有没有办法让扩展变得多态?

如何对多个字段进行分组和排序?

如何使用Jackson将XML元素与值和属性一起封装

使用While循环打印素数,无法正常工作

Java堆中的许多java.time.ZoneRegion实例.ZoneId实例不应该被缓存吗?

根本不显示JavaFX阿拉伯字母

何时调用密封层次 struct 的switch 中的默认情况

在Java泛型中使用通配符时,如何推断类型

在单例类上获取Java锁,了解原因

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序

java中的网上购物车解析错误

java构造函数中的冻结操作何时发生?

移动二维数组的行

如何使用 Java 替换位于特定标记内的 XML 标记的 CDATA 内的值