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

如果源不包含此列表,如何在目标中获取List的元素(用于映射)?

常哲彦
2023-03-14

我正在尝试映射下一个结构(在dozer中成功映射,与mapstruct有一些问题),源代码中缺少列表,如何在mapper中获取其第一个元素?目标类别:

    @Data
public class FirstLvl {
        protected List<SecondLvl> list;
        
        @Data
        public static class SecondLvl {
                protected FirstLvl.SecondLvl.ThirdLvl thirdLvl;

                @Data
                public static class ThirdLvl {
                        protected FourthLvl fourthLvl;
                }
        }
}

@Data
public class FourthLvl {
        protected FourthLvl.FithLvl fithLvl;

        @Data
        public static class FithLvl {

                protected String str1;
                protected String str2;

        }
}

资料来源:

@Data
public class FirstLvlDTO {
      protected FirstLvlDTO.SecondLvlDTO secondLvlDTO ;

        @Data
        public static class SecondLvlDTO  {
            protected FirstLvlDTO.SecondLvlDTO.ThirdLvlDTO thirdLvlDTO ;


                @Data
                public static class ThirdLvlDTO {

                        protected FourthLvlDTO fourthLvlDTO;
                }
        }

}

@Data
public class FourthLvlDTO  {

        protected String str1;

        protected String str2;

}

映射器和对象工厂:

@Mapper(uses = { ObjectFactory.class })
public interface FirstLvlDTOtoFirstLvl  {

@Mapping(target=“list[0].threeLvl.fourthLvl.fithLvl.str2”, source=“secondLvlDTO.thirdLvlDTO.fourthLvlDTO.str2”)

    FirstLvl toFirstLvl (FirstLvlDTO firstLvlDTO );
        
}

public class ObjectFactory {

    public FirstLvl createFirstLvl() {
        return new FirstLvl();
    }
    
    public FirstLvl.SecondLvl createFSLvl() {
        return new FirstLvl.SecondLvl();
    }
}

问题是我不知道如何获得列表的第一个元素(mapstruct中没有使用[]符号)。我可以将方法getlist0/setlist0添加到FirstLvl类中,以简单地返回列表的第一个元素(return list.get(0)),并在List 0 . third lvl . fourthlvl . fithlvl . str 2这样的映射器中使用它,但我不知道这是不是一个好主意,是否有可能做得更好

共有2个答案

南宫书
2023-03-14

Mapstruct不支持多对一或一对多映射,这些映射需要手动实现。

在这里,您可以找到类的工作示例:

@Mapper
public abstract class LevelMapper {

    @Mapping( target = "secondLvlDTO", source = "list" )
    public abstract FirstLvlDTO map(FirstLvl lvl);

    // used by the manual implementation to continue mapping.
    @Mapping( target = "thirdLvlDTO.fourthLvlDTO", source = "thirdLvl.fourthLvl.fithLvl" )
    protected abstract SecondLvlDTO map(SecondLvl lvl);

    // manually implementation for getting the first object from the list and converting it.
    protected SecondLvlDTO getFirst(List<SecondLvl> list) {
        return map( list.get( 0 ) );
    }

// the reverse
    
    @Mapping( target = "list", source = "secondLvlDTO" )
    public abstract FirstLvl map(FirstLvlDTO lvl);

    // used by the manual implementation to continue mapping.
    @Mapping( target = "thirdLvl.fourthLvl.fithLvl", source = "thirdLvlDTO.fourthLvlDTO" )
    protected abstract SecondLvl map(SecondLvlDTO lvl);

    // manually implementation for creating the the list and filling it with the converted dto.
    protected List<SecondLvl> asList(SecondLvlDTO dto) {
        return Arrays.asList( map( dto ) ); // or any other way to create a list.
    }
}
温亮
2023-03-14

我不确定我完全理解你的代码。我的方法应该是这样的。然而,您在列表中的类型似乎不匹配。

public interface TestMapper {

    @Mapping(target = "list0", ignore = true)
    @Mapping(target = "list", ignore = true)
    A toA(A1 a1);

    @AfterMapping
    default void mapperCode(@MappingTarget A a, A1 a1) {
        List<A.B> list = a.getList(); // target list requiures Type A.B 
        A1.B1 b1 = a1.getB1(); // source does have A1.B1 and not A.B as type
        // if your Types match set the list here manually like 
        // a.setList(List.of(a1.getB()));
    }

}

您的代码仅使用A、B、A1、B1,...。我建议你用真名。

编辑:

一个可行但非常丑陋的解决方案是手动操作。我不确定这是否对你有帮助。

public interface TestMapper {

@Mapping(target = "list", ignore = true)
FirstLvl map(FirstLvlDTO firstLvlDTO);

@AfterMapping
default void mapperCode(@MappingTarget FirstLvl firstLvl, FirstLvlDTO firstLvlDTO) {
    String str1 = firstLvlDTO.getSecondLvlDTO().getThirdLvlDTO().getFourthLvlDTO().getStr1();
    String str2 = firstLvlDTO.getSecondLvlDTO().getThirdLvlDTO().getFourthLvlDTO().getStr2();
    FirstLvl.SecondLvl secondLvl = new FirstLvl.SecondLvl();
    FirstLvl.SecondLvl.ThirdLvl thirdLvl = new FirstLvl.SecondLvl.ThirdLvl();
    secondLvl.setThirdLvl(thirdLvl);
    FourthLvl fourthLvl = new FourthLvl();
    thirdLvl.setFourthLvl(fourthLvl);
    FourthLvl.FithLvl fithLvl = new FourthLvl.FithLvl(str1, str2);
    fourthLvl.setFithLvl(fithLvl);
    firstLvl.setList(Arrays.asList(secondLvl));
}

}

@Data
public class FourthLvl {
protected FourthLvl.FithLvl fithLvl;

@Data
public static class FithLvl {

    public FithLvl(String str1, String str2){
        this.str1 = str1;
        this.str2 = str2;
    }

    protected String str1;
    protected String str2;

}

}

 类似资料:
  • 问题内容: 我有一个这样的清单: 我想获取T的.class。我该怎么做? 我的意思是: 编辑: 我尝试过: 当我调试它时 genericType 值: java.util.List 所以我认为这肯定是与该问题不同的问题:获取java.util.List的泛型类型,因为如果您使用声明了一个类并在以后的其他方法中分配了某些内容,则该类消失了。 问题答案: 您不能因为类型擦除。泛型类型在运行时未知(已被

  • 问题内容: 的HTML 码 问题答案: 我已经看到这个问题在过去大约一年左右的时间里弹出了几次,我想尝试编写此函数…所以就到这里了。它接受父元素,并删除每个子元素的textContent,直到剩下的是textNode为止。我已经在您的HTML上对其进行了测试,并且可以正常工作。 你叫它

  • 问题内容: 的HTML 码 问题答案: 我已经看到这个问题在过去大约一年左右的时间里弹出了几次,我想尝试编写此函数…所以就到这里了。它接受父元素,并删除每个子元素的textContent,直到剩下的是textNode为止。我已经在您的HTML上对其进行了测试,并且可以正常工作。 你叫它

  • (我在下面给出了一个答案,但如果有人能想出一个不那么可怕的解决方案,我会保留这个问题)。

  • 问题内容: 考虑以下: 如何获取列表中的元素数量? 问题答案: 该函数可以与Python中的几种不同类型一起使用-内置类型和库类型。例如: 官方2.x文档在这里: 官方3.x文档在这里:

  • 在寻找这个问题的答案时,我也遇到过类似的利用LINQ的方法,但是我还不能完全理解它们(并因此实现它们),因为我对它还不熟悉。基本上,我想说的是: 检查列表的任何元素是否包含特定字符串。 如果是,则获取该元素。 老实说,我不知道该如何着手做那件事。我能想出的是这个(当然不工作): 我知道为什么它不起作用: 不返回,因为它将检查列表的整个元素是否与我指定的字符串匹配 不会找到匹配项,因为它将再次检查与