<!--导入的版本,参考官网-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
// 测试方法,后续都是这样测试
@Test
void test() {
BasicMapper instance = BasicMapper.INSTANCE;
BasicUserDTO convert = instance.convert(user);
}
@Mapper
public interface BasicMapper {
// 使用入口
BasicMapper INSTANCE = Mappers.getMapper(BasicMapper.class);
BasicUserDTO convert(BasicUser user);
}
// 接口方式
@Mapper
public interface BasicMapper {
BasicMapper INSTANCE = Mappers.getMapper(BasicMapper.class);
BasicUserDTO convert(BasicUser user);
default PersonDTO convertCustom(BasicUser user) {
return PersonDTO
.builder()
.id(String.valueOf(user.getId()))
.firstName(user.getName().substring(0, user.getName().indexOf(" ")))
.lastName(user.getName().substring(user.getName().indexOf(" ") + 1))
.build();
}
}
// 抽象类方式,好处:可以直接在映射器类中声明附加字段
@Mapper
public abstract class BasicMapper {
public abstract BasicUserDTO convert(BasicUser user);
public PersonDTO convertCustom(BasicUser user) {
return PersonDTO
.builder()
.id(String.valueOf(user.getId()))
.firstName(user.getName().substring(0, user.getName().indexOf(" ")))
.lastName(user.getName().substring(user.getName().indexOf(" ") + 1))
.build();
}
}
@Mapping(source = "user.id", target = "id")
@Mapping(source = "user.name", target = "firstName")
@Mapping(source = "education.degreeName", target = "educationalQualification")
@Mapping(source = "address.city", target = "residentialCity")
@Mapping(source = "address.country", target = "residentialCountry")
PersonDTO convert(BasicUser user, Education education, Address address);
@Data
@Builder
@ToString
public class BasicUser {
private int id;
private String name;
// 嵌套对象
private List<Manager> managerList;
}
// 指定一个嵌套对象的映射类
@Mapper(uses = {ManagerMapper.class})
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "user.id", target = "id")
@Mapping(source = "user.name", target = "firstName")
@Mapping(source = "education.degreeName", target = "educationalQualification")
@Mapping(source = "address.city", target = "residentialCity")
@Mapping(source = "address.country", target = "residentialCountry")
PersonDTO convert(BasicUser user, Education education, Address address);
}
// 生成了一个managerListToManagerDTOList对嵌套类进行解析
@Mapping(source = "address.city", target = "residentialCity")
@Mapping(source = "address.country", target = "residentialCountry")
void updateExisting(Address address, @MappingTarget PersonDTO personDTO);
// 生成了一个DTO
PersonDTO personDTO = UserMapper.INSTANCE.convert(address);
// 对这个personDTO进行了更新
UserMapper.INSTANCE.updateExisting(address,personDTO);
@Mapper
public interface ManagerMapper {
ManagerMapper INSTANCE = Mappers.getMapper(ManagerMapper.class);
// 故意吧这两个顺序弄反,在测试看是否生效
@Mapping(source = "address.city", target = "residentialCountry")
@Mapping(source = "address.country", target = "residentialCity")
ManagerDTO convert(Manager manager);
@InheritConfiguration
void updateExisting(Manager manager, @MappingTarget ManagerDTO managerDTO);
}
想定义一个双向映射
如:
使用 @InheritInverseConfiguration 会自动的反转配
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
// mapping的配置效果,也会被下面的反转映射所使用
BasicUserDTO convert(BasicUser user);
@InheritInverseConfiguration // 反转映射
BasicUser convert(BasicUserDTO userDTO);
}
自定义异常
public class ValidationException extends RuntimeException {
public ValidationException(String message, Throwable cause) {
super(message, cause);
}
public ValidationException(String message) {
super(message);
}
}
自定义校检规则
public class Validator {
public int validateId(int id) throws ValidationException {
if(id < 0){
throw new ValidationException("Invalid ID value");
}
return id;
}
}
使用
// 导入校检规则
@Mapper(uses = { Validator.class})
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
// 抛出对应的异常
BasicUserDTO convert(BasicUser user) throws ValidationException;
}
数值
@Mapping(source = "employment.salary",
target = "salary",
numberFormat = "$#.00")
PersonDTO convert(BasicUser user,
Education education,
Address address,
Employment employment);
// 会自动转换,如下:
personDTO.setSalary( new DecimalFormat( "$#.00" ).format(
employment.getSalary() ) );
日期
@Mapping(source = "dateOfBirth",
target = "dateOfBirth",
dateFormat = "dd/MMM/yyyy")
ManagerDTO convert(Manager manager);
// 会自动转换,如下:
managerDTO.setDateOfBirth(
new SimpleDateFormat( "dd/MMM/yyyy" )
.parse( manager.getDateOfBirth() ) );
// 如果没自定义转换, 则生成如下:
managerDTO.setDateOfBirth( new SimpleDateFormat().parse(
manager.getDateOfBirth() ) );
通过循环遍历,进行映射。
如果使用了@Mapping的uses则会自动调用此对应的映射方法来执行元素转换。
简单使用
@Mapper
public interface CollectionMapper {
CollectionMapper INSTANCE = Mappers.getMapper(CollectionMapper.class);
Set<String> convert(Set<Long> ids);
Set<EmploymentDTO> convertEmployment(Set<Employment> employmentSet);
}
需要对实体进行自定义映射,则需要先定义实体之间的转换方法。
@Mapper
public interface CollectionMapper {
CollectionMapper INSTANCE = Mappers.getMapper(CollectionMapper.class);
// 自定义映射
@Mapping(source = "degreeName", target = "degree")
@Mapping(source = "institute", target = "college")
@Mapping(source = "yearOfPassing", target = "passingYear")
EducationDTO convert(Education education);
// 会去匹配自定义映射进行转换
List<EducationDTO> convert(List<Education> educationList);
}
// 会生成如下代码:
educationDTO.degree( education.getDegreeName() );
educationDTO.college( education.getInstitute() );
educationDTO.passingYear( education.getYearOfPassing() );
对map进行映射
@Mapper
public interface CollectionMapper {
CollectionMapper INSTANCE = Mappers.getMapper(CollectionMapper.class);
@MapMapping(keyNumberFormat = "#L", valueDateFormat = "dd.MM.yyyy")
Map<String, String> map(Map<Long, Date> dateMap);
}
// 生成如下代码:
String key = new DecimalFormat( "#L" ).format( entry.getKey() );
String value = new SimpleDateFormat( "dd.MM.yyyy" ).format( entry.getValue() );
// 使用ADDER_PREFERRED策略
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface PersonMapperAdderPreferred {
PersonDTO map(Person person);
}
@Mapper
public interface CollectionMapper {
CollectionMapper INSTANCE = Mappers.getMapper(CollectionMapper.class);
Set<String> convertStream(Stream<Long> ids);
@Mapping(source = "degreeName", target = "degree")
@Mapping(source = "institute", target = "college")
@Mapping(source = "yearOfPassing", target = "passingYear")
EducationDTO convert(Education education);
List<EducationDTO> convert(Stream<Education> educationStream);
}
// 生成如下:
return ids.map( long1 -> String.valueOf( long1 ) )
.collect( Collectors.toCollection( HashSet<String>::new ) );
public enum DegreeStream {MATHS}
public enum DegreeStreamPrefix {MSC_MATHS}
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@EnumMapping(nameTransformationStrategy = "prefix", configuration = "MSC_")
DegreeStreamPrefix convert(DegreeStream degreeStream);
@EnumMapping(nameTransformationStrategy = "stripPrefix", configuration = "MSC_")
DegreeStream convert(DegreeStreamPrefix degreeStreamPrefix);
}
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
uses = {CollectionMapper.class, ManagerMapper.class, Validator.class},
imports = UUID.class )
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "education.yearOfPassing", target = "education.passingYear",
defaultValue = "2001")
@Mapping(source = "employment", target = ".")
@Mapping(target = "residentialCountry", constant = "US")
PersonDTO convert(BasicUser user,
Education education,
Address address,
Employment employment);
}
@Mapper( imports = UUID.class )
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source = "user.id", target = "id",
defaultExpression = "java( UUID.randomUUID().toString() )")
PersonDTO convert(BasicUser user,
Education education,
Address address,
Employment employment);
}
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
}
// 使用
PersonDTO personDTO = UserMapper.INSTANCE.convert(user);
@Mapper(componentModel = "spring")
public interface UserMapper {}
// 生成如下:
@Component
public class UserMapperImpl implements UserMapper {}
// 使用
@Controller
public class UserController() {
@Autowired
private UserMapper userMapper;
}
public abstract class UserMapperDecorator implements UserMapper {
private final UserMapper delegate;
protected UserMapperDecorator (UserMapper delegate) {
this.delegate = delegate;
}
@Override
public PersonDTO convert(BasicUser user,
Education education,
Address address,
Employment employment) {
// 委托
PersonDTO dto = delegate.convert(user, education, address, employment);
if (user.getName().split("\\w+").length > 1) {
dto.setFirstName(user.getName().substring(0, user.getName().lastIndexOf(' ')));
dto.setLastName(user.getName().substring(user.getName().lastIndexOf(" ") + 1));
}
else {
dto.setFirstName(user.getName());
}
return dto;
}
}
// 使用
@Mapper
@DecoratedWith(UserMapperDecorator.class)
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
PersonDTO convert(BasicUser user, Education education, Address address, Employment employment);
}
@Mapper
@DecoratedWith(UserMapperDecorator.class)
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
// 执行前, 如果manager为null则设置一个空集合
@BeforeMapping
default void validateMangers(BasicUser user) {
if (Objects.isNull(user.getManagerList())) {
user.setManagerList(new ArrayList<>());
}
}
@Mapping(target = "residentialCountry", constant = "US")
void updateExisting( Address address );
// 执行后,对firstName和LastName进行一个字符转换
@AfterMapping
default void updateResult(BasicUser user,
@MappingTarget PersonDTO personDTO) {
personDTO.setFirstName(personDTO.getFirstName().toUpperCase());
personDTO.setLastName(personDTO.getLastName().toUpperCase());
}
}
reflectoring.io-> 文章
官网