Java - 映射具有循环依赖性的 DTO
Java - Mapping DTOs with Circular Dependencies
目前正在设置经典映射器,将实体转换为 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 中创建一个新方法,并使其不映射人员或州。但我想知道是否有已知的设计模式或更通用的方法来做到这一点?
谢谢
唯一的办法就是先构造一边:
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<State>
之类的数据结构,但我认为这不值得。您还可以通过移除一侧并在需要时将 Person
与其 States
相关联或将 Map<State, List<Person>>
存储在另一层来打破循环依赖。但我仍然更喜欢 post.
开头概述的方法
关于 side-note:也许试试 datus(免责声明:我是作者),看看它是否适合您的其他转换任务并简化您的工作:)
目前正在设置经典映射器,将实体转换为 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 中创建一个新方法,并使其不映射人员或州。但我想知道是否有已知的设计模式或更通用的方法来做到这一点?
谢谢
唯一的办法就是先构造一边:
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<State>
之类的数据结构,但我认为这不值得。您还可以通过移除一侧并在需要时将 Person
与其 States
相关联或将 Map<State, List<Person>>
存储在另一层来打破循环依赖。但我仍然更喜欢 post.
关于 side-note:也许试试 datus(免责声明:我是作者),看看它是否适合您的其他转换任务并简化您的工作:)