我有一个 Web 项目,其中我展示了一个 WS api,它使用 CXF 用于 WS,Spring 用于 DI,Hibernate 用于持久性,目前使用 Orika 用于 DO-DTO 映射。这是我的两个实体:
@Entity
public class Course {
@Id
private Long courseId;
@Column
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "scheduleId")
private Schedule schedule;
...
}
@Entity
public class Schedule {
@Id
private Long scheduleId;
@Column
private String name;
@OneToMany(mappedBy="schedule")
private List<Course> courses;
...
}
我的问题是关于创建 DTO 对象时的正确方法。如您所见,这些对象具有双向关系,因此当 CXF 将它们编组为 WebService 的 XML 时,创建 1:1 DTO 将导致循环引用。
这是我到目前为止所做的:
@Service("scheduleService")
public class ScheduleService extends AbstractService implements IScheduleService{
@Autowired
private IScheduleDAO scheduleDAO;
public List<ScheduleDTO> getSchedules() {
List<ScheduleDTO> schedulesDTO = new ArrayList<ScheduleDTO>();
List<Schedule> schedules = scheduleDAO.findAll();
for(Schedulep:schedules) {
schedulesDTO.add(this.map(p, ScheduleDTO.class));
}
return schedulesDTO;
}
@Override
@Transactional(readOnly=true)
public ScheduleDTO getSchedule(Long id) {
Schedule schedule = scheduleDAO.findById(id);
ScheduleDTO scheduleDTO = new ScheduleDTO();
this.map(schedule, scheduleDTO);
return scheduleDTO;
}
@Override
@Transactional(readOnly=true)
public ScheduleWithCoursesDTO getScheduleWithCourses(Long id) {
//loads schedule object and join fetchs all associated courses
Schedule schedule = scheduleDAO.findWithCourses(id);
ScheduleWithCoursesDTO sch = this.map(schedule, ScheduleWithCoursesDTO.class);
return sch;
}
}
如您所见,我有一个ScheduleDTO
只有基本属性(没有关系)的对象,然后是一个“特殊” ,其中包含一个仅包含基本属性ScheduleWithCoursesDTO
的类列表。CourseDTO
这种方式让我感觉很尴尬;我可以想到需要使用 检索所有课程的Schedule
用例,以及需要使用关联的时间表检索课程的用例。为您可能需要的每种关系组合创建这些“特殊 DTO”对象是否是通常的程序?还有另一种我想念的方式吗?也许有一种方法可以告诉 Orika 或任何其他映射器忽略给定映射执行的某些属性(而不是全局配置它)。
计划DTO:
public class ScheduleDTO {
private Long scheduleId;
private String name;
}
ScheduleWithCoursesDTO
public class ScheduleWithCoursesDTO extends ScheduleDTO {
private List<CourseDTO> courses;
}