【问题标题】:Java - Mapping DTOs with Circular DependenciesJava - 使用循环依赖映射 DTO
【发布时间】:2019-10-13 05:16:37
【问题描述】:

当前设置经典映射器,将实体转换为 DTO。 一些实体(以及 DTO)相互引用(在特定的 JPA 实体定义之后)。

假设:

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
}

有了这样的循环依赖,我必须像这样设置映射器:

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;
   }

轻松避免这种情况的一种方法是在 PersonMapper 或 StateMapper 中创建一个新方法,并使其不映射人员或状态。但我想知道是否有已知的设计模式或更通用的方式来做到这一点?

谢谢

【问题讨论】:

    标签: java design-patterns circular-dependency


    【解决方案1】:

    唯一的办法是先构造一侧:

    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;
      }
    }
    

    其他一切都会使用一些Reference&lt;State&gt; 之类的数据结构,但我认为这不值得。您还可以通过删除一侧并在需要时将Person 与其States 关联或将Map&lt;State, List&lt;Person&gt;&gt; 存储在另一个级别来打破循环依赖关系。但我仍然更喜欢文章开头概述的方法。

    附带说明:也许可以试试datus(免责声明:我是作者),看看它是否适合您的其他转换任务并简化您的工作:)

    【讨论】:

      猜你喜欢
      • 2021-01-08
      • 2019-12-21
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多