简体   繁体   English

Java - 使用循环依赖关系映射DTO

[英]Java - Mapping DTOs with Circular Dependencies

Currently settings up classic mappers, converting Entities to DTOs. 目前设置经典映射器,将实体转换为DTO。 Some of the entities (and thus DTOs) reference each other (after specific JPA entity definition). 一些实体(以及因此DTO)相互引用(在特定JPA实体定义之后)。

Let's say: 让我们说:

public class Person {
  private String name;
  private List<State> states; // All states with this person
  // Getters & Setters
}

public class State {
  private String name;
  private List<Person> persons; // All persons with this state
   // Getters & Setters
}

With such circular dependencies I have to set up mappers like so: 有了这样的循环依赖,我必须像这样设置映射器:

public class PersonMapper {
   public PersonDTO toDTO(Person p) { // not null
     PersonDTO dto = new PersonDTO();
     dto.setName(p.getName());
     dto.setStates(p.States().stream().map(stateMapper::toDTO).collect(Collectors.toList());
     return dto;
   }

public class StateMapper {
   public StateDTO toDTO(State s) { // not null
     StateDTO dto = new StateDTO();
     dto.setName(s.getName()); 
     dto.setPersons(s.getPersons().stream().map(personMapper::toDTO).collect(Collectors.toList());
     return dto;
   }

One way to easily avoid this is to create a new method in PersonMapper or StateMapper and make it NOT map the persons or states. 容易避免这种情况的一种方法是在PersonMapper或StateMapper中创建一个新方法,并使其不映射人或状态。 But I was wondering if there was a known design pattern or a more generic way of doing this? 但我想知道是否有一个已知的设计模式或更通用的方式这样做?

Thanks 谢谢

The only way is to construct one side first: 唯一的方法是先构建一面:

public class PersonMapper {
   public PersonDTO toDTO(Person p) { // not null
     PersonDTO dto = new PersonDTO();
     dto.setName(p.getName());
     dto.setStates(new ArrayList<>());
     states.forEach(state -> state.getPersons().add(dto)) //todo: uniqueness check
     return dto;
   }
}

public class StateMapper {
   //todo: maybe Person.name is better than the whole Person object in the map
   public StateDTO toDTO(State s, Map<Person, PersonDTO> personMapping) { 
     StateDTO dto = new StateDTO();
     dto.setName(s.getName()); 

     List<PersonDTO> persons = s.getPersons().stream().map(personMapping::get)
                               .collect(Collectors.toList();
     persons.forEach(p -> p.getStates().add(dto)) //todo: uniqueness check for states or use a set
     dto.setPersons(persons);

     return dto;
  }
}

Everything else would use some Reference<State> like data structure but I don't think thats worth it. 其他一切都会使用一些Reference<State>类的数据结构,但我认为这不值得。 You could also break the circular dependency by removing one side and correlate a Person to its States when needed or store a Map<State, List<Person>> on another level. 您也可以通过删除一方打破循环依赖和相关Person到其States需要时或存储Map<State, List<Person>>在另一个层面上。 But I still prefer the approach outlined at the start of my post. 但我仍然更喜欢在帖子开头概述的方法。

On a side-note: Maybe try datus (disclaimer: I am the author) and see if it fits your other conversion tasks and ease your work :) 在旁注:也许尝试datus (免责声明:我是作者)并查看它是否适合您的其他转换任务并简化您的工作:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM