PO(Persistent Object):持久化对象,常在Dao层中使用
Entity:实体类
DTO(Data Transfer Object):Service层中使用,表示数据传输对象
VO(View Object):表示层对象,是页面显示的数据对象,即数据返回
POJO(Plain Ordinary Java Object):中间对象,随意转换为各类对象
一般来说,这些类有大量重复的代码,他们之间进行转换会频繁调用get和set方法,MapStruct应运而生
一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现。
生成的映射代码使用简单的方法调用,因此速度快、类型安全且易于理解。
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.2.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
</dependency>
package com.example.dozer.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
private String username;
private String password;
private int age;
}
package com.example.dozer.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String pwd;
private int age;
}
package com.example.dozer.mapper;
import com.example.dozer.dto.UserDTO;
import com.example.dozer.entity.User;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserConvertMapper {
//获取mapper对象使用mapStruct的Mappers.getMapper()
UserConvertMapper instance = Mappers.getMapper(UserConvertMapper.class);
//转化UserDTO-->User
User userConvert(UserDTO userDTO);
}
package com.example.dozer.controller;
import com.example.dozer.dto.UserDTO;
import com.example.dozer.entity.User;
import com.example.dozer.mapper.UserConvertMapper;
public class TestController {
public static void main(String[] args) {
//模拟数据
UserDTO userDTO = new UserDTO();
userDTO.setUsername("zhangsan");
userDTO.setPassword("1246asd");
userDTO.setAge(16);
//获取实例进行转换
User user = UserConvertMapper.instance.userConvert(userDTO);
System.out.println(user);
}
}

如上方代码我们有两个类,UserDTO和User,两者需要进行转化,但是User和UserDTO相比,有两个属性不同

按照MapStruct默认规则(@Mapper注解实现自动转化)无法进行转化所以为null
而age属性名称相同所以可以转化
到这里大家别嫌MapStruct菜,怎么也不能直接一步搞定,你自己想想,程序又不是人,他怎么知道你的属性名称的对应呢!
所以我们继续。。。。
我们使用@Mappings和@Mapping的配合使用完成自定义映射
以下我们修改上方QuickStart中的Mapper接口,在转换方法上使用@Mappings配合@Mapping进行自定义映射规则使用
但你也可以直接写多个@Mapping不需要使用@Mappings包裹
package com.example.dozer.mapper;
import com.example.dozer.dto.UserDTO;
import com.example.dozer.entity.User;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserConvertMapper {
//获取mapper对象使用mapStruct的Mappers.getMapper()
UserConvertMapper instance = Mappers.getMapper(UserConvertMapper.class);
//转化UserDTO-->User
@Mappings(
{
@Mapping(source = "username", target = "name"),
@Mapping(source = "password", target = "pwd")
}
)
User userConvert(UserDTO userDTO);
}
再次测试转化成功

用于设定自定义的映射规则
参数如下:
@Mapping(target="xxx",ignore=true)其实不用想的太复杂,引用类型也是基础类型构成的所以我们只要完成引用类型内部转化即可完成引用类型的转换了!
package com.example.dozer.entity;
import com.example.dozer.po.UserPO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String pwd;
private int age;
private UserPO userPO;
}
package com.example.dozer.dto;
import com.example.dozer.pojo.UserPojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
private String username;
private String password;
private int age;
private UserPojo userPojo;
}
package com.example.dozer.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserPO {
private String cname;
private int age;
}
package com.example.dozer.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserPojo {
private String childName;
private int age;
}
package com.example.dozer.mapper;
import com.example.dozer.dto.UserDTO;
import com.example.dozer.entity.User;
import com.example.dozer.po.UserPO;
import com.example.dozer.pojo.UserPojo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserConvertMapper {
//获取mapper对象使用mapStruct的Mappers.getMapper()
UserConvertMapper instance = Mappers.getMapper(UserConvertMapper.class);
//转化UserDTO-->User
@Mappings(
{
@Mapping(source = "username", target = "name"),
@Mapping(source = "password", target = "pwd"),
@Mapping(source = "userPojo" ,target = "userPO")
}
)
User userConvert(UserDTO userDTO);
@Mapping(source = "childName",target = "cname")
UserPO userPojoToPO(UserPojo userPojo);
}
package com.example.dozer.controller;
import com.example.dozer.dto.UserDTO;
import com.example.dozer.entity.User;
import com.example.dozer.mapper.UserConvertMapper;
import com.example.dozer.pojo.UserPojo;
public class TestController {
public static void main(String[] args) {
//模拟数据
UserDTO userDTO = new UserDTO();
userDTO.setUsername("zhangsan");
userDTO.setPassword("1246asd");
userDTO.setUserPojo(new UserPojo("cc",2));
userDTO.setAge(16);
//获取实例进行转换
User user = UserConvertMapper.instance.userConvert(userDTO);
System.out.println(user);
}
}

@AfterMapping实现属性自定义映射处理@AfterMapping表示让MapStruct在调用完自动转化方法后再调用这个方法
如下,我设置一个若值为空则默认填入default字符串的方法
@AfterMapping
default void UserDTOToUser(UserDTO userDTO, @MappingTarget User user){
if ("".equals(userDTO.getUsername())||userDTO.getUsername()==null){
user.setName("default");
}
}
我们只需要设置如下示例类似的写法即可
List<UserDTO> userToUserDto(List<User> userList)
没错就是这么简单,因为我们在前面设置了UserDTO转为User的方法,所以批量本质实际就是多次的调用单个转换
目的是为了完全自主的进行操作,更加灵活自由完成业务逻辑
主要属性:
ignoreByDefalut:忽略默认映射行为,避免不必要赋值、覆盖等操作
在方法上使用@InheritConfiguration就可以实现在我们写相同逻辑时直接继承原始方法上的@Mapping注解声明的内容,然后其他自己定义即可
@InheritConfiguration
void updateUserToUserDTO(User user,@MappingTarget UserDTO userDto)
即我不用再在需要反向映射的方法上设置@Mapping进行源和目标的设置,直接使用该注解完成
比如我已经写好了UserDTO转User的我使用这个注解可以直接完成User转UserDTO的方法不需要再写一遍反向的@Mapping配置了
我们要做到只要设置一下name属性,标注对哪个方法进行反向映射即可
@InheritInverseConfiguration(name="userToUserDTO")
User userDTOTOUser(UserDTO userDTO);
我们通过前面的使用知道@Mapper就是用来标注当前类或接口一个MapStruct的转化Mapper
当我们需要在Spring中进行使用时,我们需要指明@Mapper注解中的一个参数:componentModel = "spring"即可
@Mapper(componentModel = "spring")
public interface UserConvertMapper {}
设置好之后就可以在类中使用@AutoWired进行注入
实质上就是生成了@Component注解,所以说我们还可以通过加@Component实现注入