【MapStruct】还在用BeanUtils?不如试试MapStruct
1. 什么是MapStruct
MapStruct是一个Java注解处理器,它可以简化Java bean之间的转换。它使用基于生成器的方法创建类型安全的映射代码,这些代码在编译时生成,并且比反射更快、更可靠。使用MapStruct可以避免手动编写大量重复的转换代码,从而提高生产力和代码质量。
MapStruct通过使用注解,在源代码中指定映射规则,MapStruct可以自动生成转换器代码。MapStruct支持各种转换场景,包括简单类型、集合、继承、日期、枚举、嵌套映射等等。同时,它还能够与Spring和CDI等IoC容器无缝集成,方便地将MapStruct转换器注入到应用程序中。
MapStruct的官网:MapStruct – Java bean mappings, the easy way!
在开发中比较常用的用来实现JavaBean之间的转换应该就是org.springframework.beans.BeanUtils
,它俩有以下区别:
- 编译时生成代码 vs 运行时反射:
MapStruct
生成的映射代码是在编译时生成的,而BeanUtils
则是在运行时使用反射机制实现转换。 - 性能和可扩展性:由于MapStruct生成的代码是类型安全的,因此可以比使用反射更加高效和可靠。同时,MapStruct还能够自定义转换逻辑并支持扩展,使得它更加灵活和可扩展。
- 集成方式:MapStruct可以无缝集成到Spring中,也可以与其他IoC容器结合使用;而BeanUtils是Spring框架自带的工具类。
- 映射规则的定义方式:MapStruct使用基于注解的方式在源代码中定义映射规则,而BeanUtils则需要手动编写复杂的转换方法。
2. 为什么使用MapStruct
在一些高并发的场景,性能是开发者十分重视的,BeanUtils
虽然也可以方便地完成JavaBean之间的转换,但是由于其底层是基于反射实现的,在高并发场景下难免会出现大规模的数据处理和转换操作,这时候还是用BeanUtils
会导致接口响应速度有所下降。
这时候,最最最高效的方法就是手动get/set,但是这种需要反复写大量重复的转换代码,并且这些代码难以被反复利用,于是就考虑使用MapStruct。
MapStruct是一种基于注解的代码生成器,它通过生成优化的映射代码来实现高性能的Bean映射。与BeanUtils相比,MapStruct在生成的映射代码中使用了更少的反射调用,并且在类型转换时可以直接使用Javac编译器已经提供的类型转换逻辑,从而避免了额外的性能开销。此外,由于MapStruct是基于注解的,它还可以提供更好的类型检查和编译时错误提示。
以下是当前比较常用的JavaBean之间转化的工具的性能对比:
可见,随着转化次数的增加只有
MapStruct
的性能最接近get/set的效率。
因此,在高并发场景下,使用MapStruct可以更有效地利用系统资源,提高系统的吞吐量和响应速度。
3. 如何使用MapStruct
接下来用一个案例来说说如何使用MapStruct
,更多详细的用法可以查看官方文档。
温馨提示:在生成get/set方法的时候,最好不要用lombok,不然有可能会出现一些奇奇怪怪的问题
先引入依赖:
<!-- MapStruct begin -->
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
<!-- MapStruct end -->
Student类:
public class Student {
private String sId;
private String sName;
private String sSex;
public String getsId() {
return sId;
}
public void setsId(String sId) {
this.sId = sId;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public String getsSex() {
return sSex;
}
public void setsSex(String sSex) {
this.sSex = sSex;
}
}
StudentVo类:
public class StudentVo {
private String id;
private String name;
private String sSex;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getsSex() {
return sSex;
}
public void setsSex(String sSex) {
this.sSex = sSex;
}
}
现在模拟两个业务:
- Student类 转 StudentVo类
- StudentVo类 转 Student类
首先,需要定义一个对象接口映射的接口
/**
* @description:对象接口映射
* @author:lrk
* @date: 2023/6/2
*/
@MapperConfig
public interface IMapping<SOURCE, TARGET> {
/**
* 映射同名属性
* @param var1 源
* @return 结果
*/
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
TARGET sourceToTarget(SOURCE var1);
/**
* 映射同名属性,反向
* @param var1 源
* @return 结果
*/
@InheritInverseConfiguration(name = "sourceToTarget")
SOURCE targetToSource(TARGET var1);
/**
* 映射同名属性,集合形式
* @param var1 源
* @return 结果
*/
@InheritConfiguration(name = "sourceToTarget")
List<TARGET> sourceToTarget(List<SOURCE> var1);
/**
* 反向,映射同名属性,集合形式
* @param var1 源
* @return 结果
*/
@InheritConfiguration(name = "targetToSource")
List<SOURCE> targetToSource(List<TARGET> var1);
/**
* 映射同名属性,集合流形式
* @param stream 源
* @return 结果
*/
List<TARGET> sourceToTarget(Stream<SOURCE> stream);
/**
* 反向,映射同名属性,集合流形式
* @param stream 源
* @return 结果
*/
List<SOURCE> targetToSource(Stream<TARGET> stream);
}
这个接口上需要加org.mapstruct.MapperConfig
的注解,表示这是一个构造器。
接下来,就需要构造一个具体类的转换配置了,需要继承IMapping
接口
这里就模拟转换两个类的相互转化,其他比如List的转换可以自主实现
/**
* @description:学生类转换配置
* @author:lrk
* @date: 2023/6/2
*/
@Mapper(
// 指定依赖注入框架
componentModel = "spring",
unmappedTargetPolicy = ReportingPolicy.IGNORE,
unmappedSourcePolicy = ReportingPolicy.IGNORE
)
public interface StudentMapping extends IMapping<Student, StudentVo>{
/**
* Student 转 StudentVo
* @param var1 源
* @return
*/
@Mapping(target = "id", source = "sId")
@Mapping(target = "name", source = "sName")
@Override
StudentVo sourceToTarget(Student var1);
/**
* StudentVo 转 Student
* @param var1 源
* @return
*/
@Mapping(target = "sId", source = "id")
@Mapping(target = "sName", source = "name")
@Override
Student targetToSource(StudentVo var1);
}
- 继承接口的泛型为
<Student, StudentVo>
,指定了Student
是源,StudentVo
是目标。 - 接口上需要有
org.mapstruct.Mapper
注解,注解里面有三个参数componentModel
:指定依赖注入框架,目前只支持spring
与CDI
unmappedTargetPolicy
:在映射方法的目标对象的属性未填充源值时应用的默认报告策略。ERROR
:任何未映射的目标属性都将导致映射代码生成失败WARN
:任何未映射的目标属性都将在构建时导致警告IGNORE
:忽略未映射的目标属性
unmappedSourcePolicy
:同上
- 认真观察Student与StudentVo可以看见,两个类除了成员变量
sSex
一样外,其余的成员变量属性均不一样,这时候可以使用org.mapstruct.Mapping
注解在接口方法上Mapping
:当属性在目标实体中具有不同的名称时,可以通过注释指定其名称
编写测试代码
@Resource
private IMapping<Student, StudentVo> studentMapping;
@Test
public void test_mapstruct() {
Student student = new Student();
student.setsId("10086");
student.setsName("张三");
student.setsSex("男");
StudentVo studentVo = studentMapping.sourceToTarget(student);
log.info("Student:{} 转 StudentVo:{}", JSONUtil.toJsonStr(student), JSONUtil.toJsonStr(studentVo));
Student student1 = studentMapping.targetToSource(studentVo);
log.info("StudentVo:{} 转 Student:{}", JSONUtil.toJsonStr(studentVo), JSONUtil.toJsonStr(student1));
}
细心的你估计已经发现了,为什么这里可以用
@Resource
将IMapping<Student, StudentVo>
注入,代码中并没有看见将其放进Spring
容器呀?别急,前面说到MapStruct的转换代码是在编译时生成的,查看编译生成的代码可以发现其中已经加入了
@Component
注解并实现了StudentMapping
@Component public class StudentMappingImpl implements StudentMapping { public StudentMappingImpl() { } public List<StudentVo> sourceToTarget(List<Student> var1) { if (var1 == null) { return null; } else { List<StudentVo> list = new ArrayList(var1.size()); Iterator var3 = var1.iterator(); while(var3.hasNext()) { Student student = (Student)var3.next(); list.add(this.sourceToTarget(student)); } return list; } } public List<Student> targetToSource(List<StudentVo> var1) { if (var1 == null) { return null; } else { List<Student> list = new ArrayList(var1.size()); Iterator var3 = var1.iterator(); while(var3.hasNext()) { StudentVo studentVo = (StudentVo)var3.next(); list.add(this.targetToSource(studentVo)); } return list; } } public List<StudentVo> sourceToTarget(Stream<Student> stream) { return stream == null ? null : (List)stream.map((student) -> { return this.sourceToTarget(student); }).collect(Collectors.toCollection(ArrayList::new)); } public List<Student> targetToSource(Stream<StudentVo> stream) { return stream == null ? null : (List)stream.map((studentVo) -> { return this.targetToSource(studentVo); }).collect(Collectors.toCollection(ArrayList::new)); } public StudentVo sourceToTarget(Student var1) { if (var1 == null) { return null; } else { StudentVo studentVo = new StudentVo(); studentVo.setId(var1.getsId()); studentVo.setName(var1.getsName()); studentVo.setsSex(var1.getsSex()); return studentVo; } } public Student targetToSource(StudentVo var1) { if (var1 == null) { return null; } else { Student student = new Student(); student.setsId(var1.getId()); student.setsName(var1.getName()); student.setsSex(var1.getsSex()); return student; } } }
这是因为前面在
StudentMapping
指定了依赖注入框架为Spring
的原因,所以生成的代码自动将其放进容器,方便我们开发者使用。
1、什么是MapStruct
1.1 JavaBean 的困扰
对于代码中 JavaBean之间的转换, 一直是困扰我很久的事情。在开发的时候我看到业务代码之间有很多的 JavaBean 之间的相互转化, 非常的影响观感,却又不得不存在。我后来想的一个办法就是通过反射,或者自己写很多的转换器。
第一种通过反射的方法确实比较方便,但是现在无论是 BeanUtils, BeanCopier 等在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。但是像这种的话,需要类型和名称都一样才会进行映射,有很多时候,由于不同的团队之间使用的名词不一样,还是需要很多的手动 set/get 等功能。
第二种的话就是会很浪费时间,而且在添加新的字段的时候也要进行方法的修改。不过,由于不需要进行反射,其性能是很高的。
1.2 MapStruct 带来的改变
MapSturct 是一个生成类型安全,高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。
-
注解处理器
-
可以生成 JavaBean 之间那的映射代码
-
类型安全,高性能,无依赖性
2、MapStruct 入门
2.1 添加依赖
-
<dependency>
-
<groupId>org.projectlombok</groupId>
-
<artifactId>lombok</artifactId>
-
<version>1.16.20</version>
-
<scope>provided</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.mapstruct</groupId>
-
<artifactId>mapstruct-jdk8</artifactId>
-
<version>${org.mapstruct.version}</version>
-
</dependency>
-
<dependency>
-
<groupId>org.mapstruct</groupId>
-
<artifactId>mapstruct-processor</artifactId>
-
<version>${org.mapstruct.version}</version>
-
</dependency>
-
<dependency>
-
<groupId>cn.hutool</groupId>
-
<artifactId>hutool-all</artifactId>
-
<version>5.1.0</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
<scope>test</scope>
-
</dependency>
2.2 po类
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
}
2.3 dto类
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
}
2.4 创建转换接口
-
//可以使用abstract class代替接口
-
-
public interface UserMapper {
-
-
UserDto userToUserDto(User user);
-
//集合
-
List<UserDto> userToUserDto(List<User> users);
-
}
2.5 测试方法
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
UserDto userDto = mapper.userToUserDto(user);
-
System.out.println(userDto);
-
}
2.6 运行效果
2.7 查看编译的class
底层通过自动取值赋值操作完成
3、MapStruct优点分析
3.1 性能高
这是相对反射来说的,反射需要去读取字节码的内容,花销会比较大。而通过 MapStruct 来生成的代码,其类似于人手写。速度上可以得到保证。
3.2 使用简单
如果是完全映射的,使用起来肯定没有反射简单。用类似 BeanUtils 这些工具一条语句就搞定了。但是,如果需要进行特殊的匹配(特殊类型转换,多对一转换等),其相对来说也是比较简单的。
基本上,使用的时候,我们只需要声明一个接口,接口下写对应的方法,就可以使用了。当然,如果有特殊情况,是需要额外处理的。
3.3 代码独立
生成的代码是对立的,没有运行时的依赖。
3.4 易于 debug
在我们生成的代码中,我们可以轻易的进行 debug。
4、MapStruct使用案例
4.1 属性名称相同
在实现类的时候,如果属性名称相同,则会进行对应的转化。通过此种方式,我们可以快速的编写出转换的方法。(入门案例)
4.2 属性名不相同
属性名不相同,在需要进行互相转化的时候,则我们可以通过@Mapping
注解来进行转化。
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String password;
-
}
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String pwd;
-
}
-
-
public interface UserMapper {
-
//单个属性
-
//@Mapping(source = "pwd",target = "password")
-
//多个属性
-
-
-
-
UserDto userToUserDto(User user);
-
}
-
source 需要转换的对接,通常是入参
-
target 转换的对接,通常是出参
-
ignore 忽略,默认false不忽略,需要忽略设置为true
-
defaultValue 默认值
-
expressions 可以通过表达式来构造一些简单的转化关系。虽然设计的时候想兼容很多语言,不过目前只能写Java代码。
-
-
-
-
-
public PersonVo PersonToPersonVo(Person person);
这里用到演示了如何使用TimeAndFormat对time和format操作,这里必须要指定需要使用的Java类的完整包名,不然编译的时候不知道你使用哪个Java类,会报错。
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
user.setPwd("123456");
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
UserDto userDto = mapper.userToUserDto(user);
-
System.out.println(userDto);
-
}
4.3 转换非基础类型属性
如果subUser与subUserDto字段名称相同直接配置即可完成(对象类型,包括list)
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String password;
-
private List<SubUserDto> subUserDto;
-
}
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String pwd;
-
private List<SubUser> subUser;
-
}
-
-
-
-
-
UserDto userToUserDto(User user);
4.4 Mapper 中使用自定义的转换
有时候,对于某些类型,无法通过代码生成器的形式来进行处理。那么, 就需要自定义的方法来进行转换。这时候,我们可以在接口(同一个接口,后续还有调用别的 Mapper 的方法)中定义默认方法(Java8及之后)。
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String password;
-
private SubUserDto subUserDto;
-
}
-
-
-
public class SubUserDto {
-
private Boolean result;
-
private String name;
-
}
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String pwd;
-
private SubUser subUser;
-
}
-
-
-
public class SubUser {
-
private Integer deleted;
-
private String name;
-
}
-
-
public interface UserMapper {
-
-
-
-
-
UserDto userToUserDto(User user);
-
-
default SubUserDto subSource2subTarget(SubUser subUser) {
-
if (subUser == null) {
-
return null;
-
}
-
SubUserDto subUserDto = new SubUserDto();
-
subUserDto.setResult(!subUser.getDeleted().equals(0));
-
subUserDto.setName(subUser.getName()==null?"":subUser.getName());
-
return subUserDto;
-
}
-
}
只能存在一个default修饰的方法
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
user.setPwd("123456");
-
SubUser subUser =new SubUser();
-
subUser.setDeleted(0);
-
subUser.setName("rkw");
-
user.setSubUser(subUser);
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
UserDto userDto = mapper.userToUserDto(user);
-
System.out.println(userDto);
-
}
4.5 多转一
我们在实际的业务中少不了将多个对象转换成一个的场景。MapStruct 当然也支持多转一的操作。
-
-
public class SubUser {
-
private Integer deleted;
-
private String name;
-
}
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String pwd;
-
}
-
-
public interface UserMapper {
-
-
-
-
-
NewUserDto userToUserDto(User user,SubUser subUser);
-
}
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
user.setPwd("123456");
-
SubUser subUser =new SubUser();
-
subUser.setDeleted(0);
-
subUser.setName("rkw");
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
NewUserDto userDto = mapper.userToUserDto(user,subUser);
-
System.out.println(userDto);
-
}
4.5.1 遵循原则
-
当多个对象中, 有其中一个为 null, 则会直接返回 null
-
如一对一转换一样, 属性通过名字来自动匹配。因此, 名称和类型相同的不需要进行特殊处理
-
当多个原对象中,有相同名字的属性时,需要通过 @Mapping 注解来具体的指定, 以免出现歧义(不指定会报错)。如上面的 name
属性也可以直接从传入的参数来赋值
-
-
-
DeliveryAddress personAndAddressToDeliveryAddressDto(Person person, String name);
4.6 更新 Bean 对象
有时候,我们不是想返回一个新的 Bean 对象,而是希望更新传入对象的一些属性。这个在实际的时候也会经常使用到。
-
-
public interface UserMapper {
-
-
NewUserDto userToNewUserDto(User user);
-
-
/**
-
* 更新, 注意注解 @MappingTarget
-
* 注解 @MappingTarget后面跟的对象会被更新。
-
*/
-
void updateDeliveryAddressFromAddress(SubUser subUser,; NewUserDto newUserDto)
-
}
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
SubUser subUser =new SubUser();
-
subUser.setDeleted(0);
-
subUser.setName("rkw");
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
NewUserDto userDto = mapper.userToNewUserDto(user);
-
mapper.updateDeliveryAddressFromAddress(subUser,userDto);
-
System.out.println(userDto);
-
}
4.7 map映射
-
-
public Map<String ,String> DateMapToStringMap(Map<String,Date> sourceMap);
-
-
public void mapMappingTest(){
-
Map<String,Date> map=new HashMap<>();
-
map.put("key1",new Date());
-
map.put("key2",new Date(new Date().getTime()+9800000));
-
Map<String, String> stringObjectMap = TestMapper.MAPPER.DateMapToStringMap(map);
-
}
4.8 多级嵌套
只需要在mapper接口中定义相关的类型转换方法即可,list类型也适用
4.8.1 方式1
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private Boolean isDisable;
-
private List<SubUser> user;
-
}
-
-
-
public class SubUser {
-
private Integer deleted;
-
private String name;
-
private List<SubSubUser> subUser;
-
}
-
-
public class SubSubUser {
-
private String aaa;
-
private String ccc;
-
}
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String isDisable;
-
private List<SubUserDto> user;
-
}
-
-
public class SubUserDto {
-
private Integer deleted;
-
private String name;
-
private List<SubSubUserDto> subUser;
-
}
-
-
public class SubSubUserDto {
-
private String aaa;
-
private String bbb;
-
}
-
-
public interface UserMapper {
-
-
UserDto userToNewUserDto(User user);
-
-
//子集字段相同方法不用编写会自动生成
-
-
//孙子集字段不相同(list会自动读取此方法生成list)
-
-
SubSubUserDto bbb(SubSubUser subSubUser);
-
-
}
4.8.2 方式2
通过uses配置类型转换
-
-
public interface UserMapper {
-
UserDto userToNewUserDto(User user);
-
}
-
-
public interface TestMapper {
-
-
SubSubUserDto bbb(SubSubUser subSubUser);
-
}
5、获取 mapper
5.1 通过 Mapper 工厂获取
我们都是通过 Mappers.getMapper(xxx.class)
的方式来进行对应 Mapper 的获取。此种方法为通过 Mapper 工厂获取。
如果是此种方法,约定俗成的是在接口内定义一个接口本身的实例 INSTANCE, 以方便获取对应的实例。
-
-
public interface SourceMapper {
-
-
SourceMapper INSTANCE = Mappers.getMapper(SourceMapper.class);
-
-
// ......
-
}
这样在调用的时候,我们就不需要在重复的去实例化对象了。类似下面
Target target = SourceMapper.INSTANCE.source2target(source);
5.2 使用依赖注入
对于 Web 开发,依赖注入应该很熟悉。MapSturct 也支持使用依赖注入,同时也推荐使用依赖注入。
@Mapper(componentModel = "spring")
5.3 依赖注入策略
可以选择是通过构造方法或者属性注入,默认是属性注入。
-
public enum InjectionStrategy {
-
-
/** Annotations are written on the field **/
-
FIELD,
-
-
/** Annotations are written on the constructor **/
-
CONSTRUCTOR
-
}
类似如此使用
@Mapper(componentModel = "cdi" injectionStrategy = InjectionStrategy.CONSTRUCTOR)
5.4 自定义类型转换
有时候,在对象转换的时候可能会出现这样一个问题,就是源对象中的类型是Boolean类型,而目标对象类型是String类型,这种情况可以通过@Mapper
的uses属性来实现:
-
-
public class User {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private Boolean isDisable;
-
}
-
-
public class UserDto implements Serializable {
-
private Integer id;
-
private String name;
-
private String address;
-
private Date birth;
-
private String isDisable;
-
}
-
-
public interface UserMapper {
-
UserDto userToNewUserDto(User user);
-
}
-
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;
-
}
-
}
-
}
要注意的是,如果使用了例如像spring这样的环境,Mapper引入uses类实例的方式将是自动注入,那么这个类也应该纳入Spring容器
-
-
public void userPoToUserDto() {
-
User user =new User();
-
user.setId(1);
-
user.setName("myx");
-
user.setAddress("江苏苏州");
-
user.setBirth(new Date());
-
user.setIsDisable(true);
-
SubUser subUser =new SubUser();
-
subUser.setDeleted(0);
-
subUser.setName("rkw");
-
UserMapper mapper = Mappers.getMapper(UserMapper.class);
-
UserDto userDto = mapper.userToNewUserDto(user);
-
System.out.println(userDto);
-
}