1

我有一个 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;

}

4

1 回答 1

1

是的,有一种方法,有些人喜欢拥有这种“上下文”映射。我个人不喜欢这样,我更喜欢为每个用例都有一个适当的 DTO,我想 DTO 是某种合同和/或操作/服务中涉及的数据的文档。

Orika 中的映射代码仍然是 Java 代码,我们可以重用它,像我们为“业务”代码所做的那样组织它。创建新的 DTO 没什么大不了的,我们可以随心所欲地拥有,这不是问题。您可以根据需要 NewScheduleDTO BasicInfoScheduleDTO FullDetailsS​​cheduleDTO。

如果您确实有一些需要上下文映射/条件的严重用例,您可以使用 Orika Filter API 或为每个上下文管理多个 MapperFactory。

于 2014-09-20T18:24:20.333 回答