文章目录
MapStruct官网
https://mapstruct.org/documentation/ide-support/
简介
一个用于对象转换为另外一个对象的java工具类,主要适用于两个对象的大部分属性名称都相同的场景。相比于Spring的BeanUtils.copyProperties()方法,还可以实现不同名称字段之间的属性赋值
导入依赖
以maven工程为例,引入如下依赖:
<properties>
<mapstruct.version>1.2.0.Final</mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
创建对象
public class Car {
private String make;
private int numberOfSeats;
//constructor, getters, setters etc.
}
public class CarDto {
private String make;
private int seatCount;
//constructor, getters, setters etc.
}
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class User {
private Long id;
private String username;
private String password;
private String phoneNum;
private String email;
private Role role;
}
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Role {
private Long id;
private String roleName;
private String description;
}
package com.example.demo.dto;
import lombok.Data;
@Data
public class UserRoleDto {
/**
* 用户id
*/
private Long userId;
/**
* 用户名
*/
private String name;
/**
* 角色名
*/
private String roleName;
}
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
private Long id;
private String name;
private Boolean isDisable;
private String email;
private Date birthday;
}
定义mapper
基本使用,不同的名称字段可以通过@Mapping或者@Mappings来映射
定义简单的mapper
@Mapper
public interface CarMapper {
//为客户端提供对映射器实现的访问。
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
简单mapper使用方式
package com.example.demo.mappers;
import com.example.demo.dto.CarDto;
import com.example.demo.entity.Car;
import org.junit.Test;
public class CarMapperTest {
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car("Morris", 5);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
System.out.println(carDto.toString());
}
}
定义一个绑定spring的mapper
以使用springboot为示例,@Mapper(componentModel = “spring”),表示把当前Mapper类纳入spring容器。使用时可以直接使用@Autowired注入
package com.example.demo.mappers;
import com.example.demo.dto.UserRoleDto;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
@Mapper(componentModel = "spring")
public interface UserRoleMapper {
/**
* 对象属性复制的方法
*
* @param user 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
*/
@Mappings({
@Mapping(source = "id", target = "userId"),
@Mapping(source = "username", target = "name"),
@Mapping(source = "role.roleName", target = "roleName")
})
UserRoleDto toUserRoleDto(User user);
}
绑定spring的mapper使用方式
package com.example.demo.mappers;
import com.example.demo.DemoApplication;
import com.example.demo.dto.UserRoleDto;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class UserRoleMapperTest {
// 注入Mapper
@Autowired
private UserRoleMapper userRoleMapper;
Role role = null;
User user = null;
@Before
public void before() {
role = new Role(2L, "admin", "超级管理员");
user = new User(1L, "herion", "123456", "1389999888", "123@qq.com", role);
}
@Test
public void toUserRoleDtorTest() {
UserRoleDto userRoleDto=userRoleMapper.toUserRoleDto(user);
System.out.println(userRoleDto);
}
}
定义类型转换mapper
@Mapper( uses = { BooleanStrFormat.class}),注意,这里的users属性用于引用之前定义的转换规则的类:
定义类型转换规则
package com.example.demo.format;
import org.springframework.stereotype.Component;
@Component
public class BooleanStrFormat {
public String toStr(Boolean isDisable) {
if (isDisable) {
return "Y";
} else {
return "N";
}
}
public Boolean toBoolean(String str) {
if (str.equals("Y")) {
return true;
} else {
return false;
}
}
}
package cn.com.flashspace.cloud.oms.biz.utils;
import cn.com.flashspace.cloud.framework.utils.DateUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Date;
@Component
public class CommonMapperUtil {
public Integer integerMaper(String intStr) {
Integer result = 0;
try {
result = Integer.parseInt(intStr);
} catch (Exception ex) {
}
return result;
}
public Double doubleMaper(String doubleStr) {
Double result = 0.00;
try {
Double.parseDouble(doubleStr);
} catch (Exception ex) {
}
return result;
}
public Date dateMaper(String dateStr) {
if (StringUtils.isEmpty(dateStr))
return null;
return DateUtils.parseFromStringDefaultNotError(dateStr);
}
}
定义类型转换mapper
package com.example.demo.mappers;
import com.example.demo.dto.CustomerDto;
import com.example.demo.entity.Customer;
import com.example.demo.format.BooleanStrFormat;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import java.util.List;
@Mapper(componentModel = "spring", uses = { BooleanStrFormat.class})
public interface CustomerListMapper {
@Mappings({
@Mapping(source = "name", target = "customerName"),
@Mapping(source = "isDisable", target = "disable")
})
CustomerDto customersToCustomerDto(Customer customer);
}
类型转换mapper使用
@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class CustomerMapperTest {
@Autowired
private CustomerListMapper customerListMapper;
@Test
public void customersToCustomerDtoTest(){
Customer customer = new Customer(1L, "herion",true,null,new Date());
CustomerDto customerDto = customerListMapper.customersToCustomerDto(customer);
System.out.println(customerDto.toString());
}
}
定义引用类型多个参数的mapper
@Mappings({
// 把user中的id绑定到目标对象的userId属性中
@Mapping(source = "user.id", target = "userId"),
// 把user中的username绑定到目标对象的name属性中
@Mapping(source = "user.username", target = "name"),
// 把role对象的roleName属性值绑定到目标对象的roleName中
@Mapping(source = "role.roleName", target = "roleName")
})
UserRoleDto toUserRoleDto(User user, Role role);
引用数据类型和基本数据类型多参数
@Mappings({
// 把user中的id绑定到目标对象的userId属性中
@Mapping(source = "user.id", target = "userId"),
// 把user中的username绑定到目标对象的name属性中
@Mapping(source = "user.username", target = "name"),
// 把role对象的roleName属性值绑定到目标对象的roleName中
@Mapping(source = "myRoleName", target = "roleName")
})
UserRoleDto useParameter(User user, String myRoleName);
引用类型多个参数的mapper使用方式
package com.example.demo.mappers;
import com.example.demo.DemoApplication;
import com.example.demo.dto.UserRoleDto;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class UserRoleMapperTest {
// 注入Mapper
@Autowired
private UserRoleMapper userRoleMapper;
Role role = null;
User user = null;
@Before
public void before() {
role = new Role(2L, "admin", "超级管理员");
user = new User(1L, "herion", "123456", "1389999888", "123@qq.com", role);
}
@Test
public void toUserRoleDto2Test() {
UserRoleDto userRoleDto=userRoleMapper.toUserRoleDto(user,role);
System.out.println(userRoleDto);
}
}
定义更新对象中的属性mapper
@Mappings({
@Mapping(source = "userId", target = "id"),
@Mapping(source = "name", target = "username"),
@Mapping(source = "roleName", target = "role.roleName")
})
void updateDto(UserRoleDto userRoleDto, @MappingTarget User user);
更新对象中的属性mapper使用方式
package com.example.demo.mappers;
import com.example.demo.DemoApplication;
import com.example.demo.dto.UserRoleDto;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = DemoApplication.class)
@RunWith(SpringRunner.class)
public class UserRoleMapperTest {
// 注入Mapper
@Autowired
private UserRoleMapper userRoleMapper;
Role role = null;
User user = null;
@Before
public void before() {
role = new Role(2L, "admin", "超级管理员");
user = new User(1L, "herion", "123456", "1389999888", "123@qq.com", role);
}
@Test
public void updateDtoTest() {
UserRoleDto userRoleDto=new UserRoleDto();
userRoleDto.setName("管理员");
userRoleDto.setRoleName("架构部");
userRoleDto.setUserId(2L);
System.out.println("执行前 userRoleDto:"+userRoleDto.toString());
System.out.println("执行前 user:"+user.toString());
userRoleMapper.updateDto(userRoleDto,user);
System.out.println("执行后 userRoleDto:"+userRoleDto.toString());
System.out.println("执行后 user:"+user.toString());
}
}
运行结果
执行前 userRoleDto:UserRoleDto(userId=2, name=管理员, roleName=架构部)
执行前 user:User(id=1, username=herion, password=123456, phoneNum=1389999888, email=123@qq.com, role=Role(id=2, roleName=admin, description=超级管理员))
执行后 userRoleDto:UserRoleDto(userId=2, name=管理员, roleName=架构部)
执行后 user:User(id=2, username=管理员, password=123456, phoneNum=1389999888, email=123@qq.com, role=Role(id=2, roleName=架构部, description=超级管理员))
定义list转换mapper
@Mapper(componentModel = "spring", uses = { BooleanStrFormat.class})
public interface CustomerListMapper {
@Mappings({
@Mapping(source = "name", target = "customerName"),
@Mapping(source = "isDisable", target = "disable")
})
CustomerDto customersToCustomerDto(Customer customer);
List<CustomerDto> customersToCustomerDtos(List<Customer> customers);
}
list转换mapper使用
@Test
public void customersToCustomerDtosTest(){
Customer customer1 = new Customer(1L, "herion1",true,null,new Date());
Customer customer2 = new Customer(2L, "herion2",true,null,new Date());
Customer customer3 = new Customer(3L, "herion3",true,null,new Date());
List<Customer> list=new ArrayList<Customer>();
list.add(customer1);
list.add(customer2);
list.add(customer3);
List<CustomerDto> customerDtos = customerListMapper.customersToCustomerDtos(list);
customerDtos.forEach(customer -> {
System.out.println(customer.toString());
});
}
混合忽略/格式化/赋值mapper
@Mappings({
@Mapping(source = "customer.name", target = "username"),
@Mapping(source = "customer.id", target = "id"),
//格式转换
@Mapping(source = "customer.isDisable", target = "disable"),
//日期格式转换
@Mapping(source = "customer.birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
//ignore 忽略映射
@Mapping(target = "email", ignore = true)
@Mapping(target = "type", expression = "java(cn.com.flashspace.cloud.oms.biz.enums.OrderType.OrderRootType.ENTRY_ORDER.toString())")
})
CustomerVO userCustomerToCustomerVO(Customer customer, User user);
混合忽略/格式化mapper使用
@Test
public void userCustomerToCustomerVOTest(){
Customer customer = new Customer();
customer.setId(111L);
customer.setName("herion");
customer.setIsDisable(true);
customer.setBirthday(new Date());
User user=new User();
user.setEmail("11@qq.com");
user.setId(222L);
user.setPhoneNum("13812344321");
CustomerVO customerVO = customerMapper.userCustomerToCustomerVO(customer,user);
System.out.println(customerVO.toString());
}