下面是实体到 DTO 映射和映射器以及生成的 Map Struct 实现的示例。
public abstract class User {
private int id;
private String firstName;
private String lastName;
private int age;
private LocalDateTime dateOfBirth;
private List<Address> addresses;
}
public class Address {
private int userId;
private String streetAddress;
private String city;
private String state;
private String zipCode;
}
public class Employee extends User {
private String designation;
private Employee reportingManager;
}
public class Contractor extends User {
private String contractingCompanyName;
}
public abstract class UserDTO {
private int id;
private String firstName;
private String lastName;
private int age;
private LocalDateTime dateOfBirth;
}
public class EmployeeDTO extends UserDTO {
private String designation;
private EmployeeDTO reportingManager;
}
public class ContractorDTO extends UserDTO {
private String contractingCompanyName;
}
@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION)
public abstract class UserMapper {
@BeanMapping(ignoreByDefault = true)
@SubclassMapping(source = Employee.class, target = EmployeeDTO.class)
@SubclassMapping(source = Contractor.class, target = ContractorDTO.class)
@Mapping(source = "id", target = "id")
@Mapping(source = "firstName", target = "firstName")
@Mapping(source = "lastName", target = "lastName")
public abstract UserDTO map(User user);
}
生成的映射器
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-07-14T12:56:15-0400",
comments = "version: 1.5.5.Final, compiler: javac, environment: Java 17.0.5 (Amazon.com Inc.)"
)
public class UserMapperImpl extends UserMapper {
@Override
public UserDTO map(User user) {
if ( user == null ) {
return null;
}
if (user instanceof Employee) {
return employeeToEmployeeDTO( (Employee) user );
}
else if (user instanceof Contractor) {
return contractorToContractorDTO( (Contractor) user );
}
else {
throw new IllegalArgumentException("Not all subclasses are supported for this mapping. Missing for " + user.getClass());
}
}
protected EmployeeDTO employeeToEmployeeDTO(Employee employee) {
if ( employee == null ) {
return null;
}
EmployeeDTO employeeDTO = new EmployeeDTO();
employeeDTO.setId( employee.getId() );
employeeDTO.setFirstName( employee.getFirstName() );
employeeDTO.setLastName( employee.getLastName() );
employeeDTO.setDesignation( employee.getDesignation() );
employeeDTO.setReportingManager( employeeToEmployeeDTO( employee.getReportingManager() ) );
return employeeDTO;
}
protected ContractorDTO contractorToContractorDTO(Contractor contractor) {
if ( contractor == null ) {
return null;
}
ContractorDTO contractorDTO = new ContractorDTO();
contractorDTO.setId( contractor.getId() );
contractorDTO.setFirstName( contractor.getFirstName() );
contractorDTO.setLastName( contractor.getLastName() );
contractorDTO.setContractingCompanyName( contractor.getContractingCompanyName() );
return contractorDTO;
}
我预计添加
BeanMapping#ignoreByDefault=true
只会映射显式映射的属性。但子类的情况并非如此。
我希望有一种更好的方法,而不是显式映射每个子类型并使用 InhertConfiguration 进行注释并从子类中排除其他属性。
正如MapStruct讨论中提到的,这是MapStruct版本1.5.5中的一个已知错误,并在main中修复(可能在1.6.0版本中)