模型到DTO策略

时间:2014-09-18 14:53:27

标签: spring web-services dto orika

我有一个Web项目,其中我使用CXF for WS,Spring for DI,Hibernate for persistence以及目前Orika for DO-DTO映射呈现WS api。这是我的两个实体:

@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或任何其他映射器忽略给定映射执行的某些属性(而不是全局配置)。

ScheduleDTO:

public class ScheduleDTO  {

    private Long scheduleId;

    private String name;

}

ScheduleWithCoursesDTO

public class ScheduleWithCoursesDTO extends ScheduleDTO {

   private List<CourseDTO> courses;

}

1 个答案:

答案 0 :(得分:1)

是的,有一种方式,有些人喜欢这种&#34;语境&#34;映射。 就个人而言,我不喜欢这样,我更喜欢为每个用例都有一个合适的DTO,我想DTO是一个合同和/或文档,用于操作/服务中涉及的数据。

在Orika中映射代码仍然是一个Java代码,我们可以重新使用它,按照我们为&#34; business&#34;码。 创造新的DTO并不是我们可以拥有的大不了的,它不是问题。您可以随意使用NewScheduleDTO BasicInfoScheduleDTO FullDetailsS​​cheduleDTO。

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