我想在我的 Spring 应用程序中使用 mapstruct 库将模型列表映射到 dto 列表。假设我有两个这样的模型:
public class Employee {
private Integer id;
private String name;
private Set<Phone> phones;
}
public class Phone {
private Integer id;
private String number;
}
Run Code Online (Sandbox Code Playgroud)
这是我的两个 dto:
public class EmployeeDto {
private Integer id;
private String name;
private Set<PhoneDto> phones;
}
public class PhoneDto {
private Integer id;
private String num;
}
Run Code Online (Sandbox Code Playgroud)
最后我在我的映射类中使用这个方法:
@Mappings({
@Mapping(target = "num", source = "phones.number")
})
public abstract List<EmployeeDto> toEmployeeDtoList(List<Employee> employeeList);
Run Code Online (Sandbox Code Playgroud)
java: No property named "phones.number" exists in source parameter(s).
但是当我想编译时这会返回我。我知道我的代码有问题,但我找不到对我的需要有用的东西。你能帮我解决这个问题吗?
第一个原因:您应该先指定object -> object
映射,然后才能指定collection -> collection
映射(PhoneDto -> Phone, EmployeeDto -> Employee),因为mapstruct嵌套表示法不会扩展到集合中。从我的角度来看,您不需要在映射器中保存基本的集合映射。你总是可以这样做:
employees.stream()
.map(mapper::toDto)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
注意:但是如果您需要collection -> collection
嵌套集合上的某些特定映射,则应该指定它。(在您的情况下,Set 可能使用下面的 LinkedHashSet 进行排序,如果您不指定集合 -> 集合映射,您将失去排序,因为 mapstruct 将使用 HashSet 作为Set<Phones> -> Set<PhonesDto>
转换的默认实现)。
如果映射器可以访问映射,Mapstruct 将选择所有映射链(嵌套类映射器应该位于同一类中或在@Mapper(uses=
类注释中声明)。
第二个原因:您的@Mapping(target = "num", source = "phones.number")
<<-- 不起作用,因为它不知道应该从phones
集合中的哪个元素中number
检索。就好像你正在尝试写作一样EmployeeDto.num(single record) = Emloyee.phones(multiple records).number(single record)
。
恕我直言,使用 mapstruct 的最佳实践是使用干净的接口。这表明您在实体/dto/视图/模型/等中拥有清晰透明的结构和良好的关系。如果需要更具体的东西 - 您始终可以使用@AfterMapping
或@BeforeMapping
注释指定默认方法。或者转到抽象类实现/装饰器(@DecoratedWith
映射)。
对于这种情况有一些肮脏的黑客 - @Mapping(target = "num", expression = "java(your_java_code_as_string_in_here)")但要注意:该表达式是一个字符串,并且仅在映射器创建时失败,并且在映射器中不起作用各种重构。
这是模型的示例映射(两种方式):
@Mapper
public interface EmployeeMapper {
Employee toEmployee(EmployeeDto employeeDto);
EmployeeDto toEmployeeDto(Employee employee);
@Mapping(target="number", source="num")
Phone toPhone(PhoneDto phoneDto);
@InheritInverseConfiguration
PhoneDto toPhoneDto(Phone phone);
List<EmployeeDto> toEmployeeDtoList(List<Employee> employeeList);
}
Run Code Online (Sandbox Code Playgroud)
另外值得考虑的好习惯是每个逻辑对象对使用不同的映射器。
@Mapper(uses = {PhoneMapper.class, OtherMapper.class}) // this is class level annotation.
Run Code Online (Sandbox Code Playgroud)
这里收集了很棒的例子:https ://github.com/mapstruct/mapstruct-examples/
归档时间: |
|
查看次数: |
16797 次 |
最近记录: |