Mapstruct:加入ID

时间:2018-07-11 08:41:59

标签: java mapping mapstruct

我正在使用Mapstruct将生成的DTO(地铁,xsd)映射到我们的业务域对象。我的困难是DTO实际上没有引用子对象,而是使用ID来引用关联的实例。

试图将其简化为一个简单的案例,我举了一个例子:

  1. SchoolDTO列出了教师和课程列表。一个老师 每个课程中只能通过teacherId引用该课程。

  2. 在商业领域,学校只有一个老师列表,每个老师 列出他们的课程清单。

类图:UML: DTO / Domain

最初,我希望以mapstruct语法解决此问题,例如在foreignId和Teacher ID(或某些qualifiedBy关联),伪代码的联接上,如下所示:

@Mapping(source="courses", target="teachers.courses", where="teacher.id = course.teacherId")

DTO:

public class SchoolDto {
    List<TeacherDto> teachers;
    List<CourseDto> courses;
}

public class TeacherDto {
    String id;
    String name;
}

public class CourseDto {
    String name;
    String teacherId;
}

域:

public class School {
    List<Teacher> teachers;
}

public class Teacher {
    String name;
    List<Course> courses;
}

public class Course {
    String name;
}

我现在正在使用相当大的@AfterMapping方法来解决它,但是我觉得这不是一个特殊的用例-所以也许我缺少了一些显而易见的东西。使用Mapstruct解决映射中的“连接”类型的正确/预期方式是什么?

1 个答案:

答案 0 :(得分:0)

我怀疑您可以在没有@AfterMapping的情况下执行此操作。 MapStruct是“仅”用于将一个对象映射到另一个对象,它不支持任何类型的查询来查找或联接数据。

如果您尚未使用它,这听起来像是使用上下文的一个好用例。那么@AfterMapping并不是很大:

@Mapper
public abstract class SchoolMapper {
    public School toSchool(SchoolDto school) {
        return toSchool( school, school.getCourses() );
    }

    protected abstract School toSchool(SchoolDto school, @Context List<CourseDto> courses);

    @Mapping(target = "courses", ignore = true) // see afterMappingToTeacher
    protected abstract Teacher toTeacher(TeacherDto teacher, @Context List<CourseDto> courses);

    protected abstract Course toCourse(CourseDto course);

    @AfterMapping
    void afterMappingToTeacher(@MappingTarget target, TeacherDto source, @Context List<CourseDto> courses) {
        // omitted null-checks

        List<Course> courses = new ArrayList<>();
        for(CourseDto course : courses) {
            if(course.getTeacherId().equals(source.getId())) {
                courses.add( toCourse(course) );
            }
        }

        target.setCourses( courses );
    }
}

(使用Java> = 8时,可以使用具有默认方法的接口)

如果您需要多次查询事物,则事物可以创建一个自己的类作为上下文,例如,它具有自己的方法来按老师ID查找所有课程。