当前位置: 首页 > 知识库问答 >
问题:

MapSTRt映射OneTo众多集合-不从空id创建实体

凌声
2023-03-14

我有一个与@OneToMany有关系的学生班级,比如下面的班级

public class Student {

    @Id
    @GeneratedValue
    private Long id;

    //fields

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "class_id")
    private Class classEntity;

和类实体:

public class Class {

    @Id
    @GeneratedValue
    private Long id;

    //fields
   
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @OneToMany(mappedBy = "classEntity", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
    private Set<Student> students;

我使用MapStruct将dto转换为实体,并将实体转换为dto:

学生地图绘制员。JAVA

@Mapper(componentModel = "spring", uses = {ClassMapper.class})
public interface StudentMapper extends EntityMapper<StudentDTO, Student> {

    @Mapping(source = "classEntity.id", target="classId")
    @Mapping(source = "classEntity.name", target="className")
    StudentDTO toDto(Student student);

    @Mapping(source = "classId", target="classEntity.id")
    Student toEntity(StudentDTO studentDTO);


    default Student fromId(Long id) {
        if (id == null) {
            return null;
        }
        Student entity = new Student();
        entity.setId(id);
        return entity;
    }

    default Long toId(Student student) {
        if (student == null){
            return null;
        }
        return student.getId();
    }

类映射器。JAVA

@Mapper(componentModel = "spring")
public interface ClassMapper extends EntityMapper<ClassDTO, Class> {

    @Mapping(target = "educatorId" , source = "educator.id")
    ClassDTO toDto(Class classEntity);

    @Mapping(target = "educator.id" , source = "educatorId")
    Class toEntity(ClassDTO classDTO);

    default Class fromId(Long id) {
        if (id == null) {
            return null;
        }
        Class entity = new Class();
        entity.setId(id);
        return entity;
    }

    default Long toId(Class classEntity) {
        if (classEntity == null){
            return null;
        }
        return classEntity.getId();
    }

}

这些映射器扩展了简单的EntityMapper接口

public interface EntityMapper <D, E> {

    E toEntity (D dto);

    D toDto(E entity);

    List <E> toEntity (List<D> dtoList);

    List<D> toDto (List<E> entityList);

    Set <E> toEntity (Set<D> dtoSet);

    Set<D> toDto (Set<E> entitySet);

生成StudentMapperImpl。班

public Student toEntity(StudentDTO studentDTO) {
        if ( studentDTO == null ) {
            return null;
        }

        StudentBuilder student = Student.builder();

        student.classEntity( studentDTOToClass( studentDTO ) );
        //fields
        return student.build();
    }

 protected Class studentDTOToClass(StudentDTO studentDTO) {
        if ( studentDTO == null ) {
            return null;
        }

        Class class1 = new Class();

        class1.setId( studentDTO.getClassId() );

        return class1;
    }

当我试图将学生DTO转换为学生DTO类中填充了class Id的学生实体时,一切都很好。当学生DTO中的class Id为空时,问题就开始了。然后映射器创建新的类对象并将其保存到数据库中......

不希望这样,因为不是每个学生都会分配类。我已经尝试了S中CascadeType的所有方法tudent.class但我认为问题出在我的Map结构映射器中。

最终我可以在没有mapstruct的情况下编写自己的映射程序,但我宁愿避免它。请帮帮我。

共有1个答案

孔鸿远
2023-03-14

在您的StudentMapper中,您在@Mapping注释中犯了一个错误。在ClassMapper中,你从Id转到Class,而在@Mapping注释中,你从Id转到Class。Id

对于嵌套映射,mapstruct将尝试创建包含嵌套字段的对象。这导致了你遇到的问题。

如果您按如下所示对其进行更改,它应该使用ClassMapper中的方法将Id转换为Class

    @Mapping(source = "classId", target="classEntity")
    Student toEntity(StudentDTO studentDTO);
 类似资料:
  • 我有这样一个映射实体: 我想在映射集合的注释中指定。 我使用的是Oracle数据库,它认为空值大于任何非空值。问题是在我的集成测试中,它使用h2数据库,似乎对空值的评估不同。 到目前为止,我想出了一个在内部使用函数的方法,如下所示: 这个黑客可以工作,但是它看起来很讨厌,我不喜欢仅仅因为集成测试就有这个代码的想法。正如我上面提到的,Oracle默认情况下以正确的顺序返回行,所以基本的不处理空值效果

  • 前段时间我读到关于在Spring中创建bean的文章,在为集合和映射创建bean时有一个例外。我的意思是为集合或映射创建bean,需要创建一个包装类,例如一个列表作为这个类的字段 然后它可以用于依赖注入。我想知道为什么没有包装类就不能注入它?

  • 我使用的是spring boot starter数据jpa 1.5.1。内部使用hibernate core 5.0.11的版本。最终的 我的实体看起来像这样: 区域 节日的 行动 我试图理解以下观点: > 我的映射是准确的,还是应该使用多重映射来处理这种关系,因为一个区域可以有多个节日,每个节日可以有多个动作 背景:如果我将fetch类型从LAZY改为eanger,就会出现以下错误。希望能够理解

  • 我得到以下情况: 源类: null

  • 假设我有以下映射目标。 如何从其他属性的Iterable映射到其他属性? 我可以这样做吗?

  • 主要内容:集合类型,以下是纠正/补充内容:集合(Collection)是一个将多个对象分组为一个单元的java框架。它用于存储,检索和操作汇总数据。 在JPA中,可以使用集合来持久化包装类和String的对象。JPA允许三种对象存储在映射集合中 - 基本类型,实体和嵌入式类型。 集合类型 根据要求,我们可以使用不同类型的集合来持久化对象。如下所示 - List Set Map 包中包含集合框架的所有类和接口。 以下是纠正/补充内容: 根据