官网地址:http://mapstruct.org/

MapStruct 是一个代码生成器,简化了不同的 Java Bean 之间映射的处理,所谓的映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO 层的实体(PO)和一些数据传输对象(DTO),大部分属性都是相同的,只有少部分的不同,通过 mapStruct,可以让不同实体之间的转换变的简单。我们只需要按照约定的方式进行配置即可。

MapStruct 是一个可以处理注解的 Java 编译器插件,可以在命令行中使用,也可以在 IDE 中使用。MapStruct 有一些默认配置,但是也为用户提供了自己进行配置的途径。

下面进行 MapStruct 的使用。

2. 添加依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>

3. 创建模拟类

假设数据库中有 user 表(包含 id ,用户名,地址,角色这些字段)与 role 表(包含 id ,角色名,描述这些字段)。

假设前端查询 user 的时候只需要用到 userId 、 userName 、 userAddr 与 role 的 roleId 字段时,如果将整个 user 都输出到前端会多出许多没有用的属性。更通用的方式是需要用到的属性封装成一个类( DTO ),通过传输这个类的实例来完成数据传输。

User.java

1
2
3
4
5
6
7
public class  {
private Long id;
private String name;
private String addr;
private Role role;
}

Role.java

1
2
3
4
5
6
public class Role {
private Long id;
private String name;
private String description;
}

UserRoleDto.java

1
2
3
4
5
6
7
public class UserRoleDto {
private Long userId;
private String userName;
private String userAddr;
private String roleName;
}

4. 编写映射类

新建一个 UserRoleMapper.java ,这个类用来定义 User.java 、 Role.java 和 UserRoleDto.java 之间属性对应规则。

1
2
3
4
5
6
7
8
9
10
11
@Mapper(componentModel = "spring")
public interface UserMapper { @Mappings({
@Mapping(source = "id", target = "userId"),
@Mapping(source = "name", target = "userName"),
@Mapping(source = "addr", target = "userAddr"),
@Mapping(source = "role.name", target = "roleName"),
})
UserRoleDto toUserRoleDto(User user);
}

MapStruct中的注解

  • @Mapper:注解在接口、类上,这样 MapStruct 才会去实现该接口
    • componentModel:该属性用于指定实现类的类型,有几个属性:
      • default:默认,不使用任何组建类型,可以通过Mappers.getMapper(Class) 方式获取实例对象
      • spring:在实现类上注解 @Component,可通过 @Autowired 方式注入
      • cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
      • jsr330:实现类上添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取。
  • @Mappings:配置多个@Mapping
  • @Mapping:配置属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    • source:源属性、target:目标属性
    • dateFormat:可将 String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat 的日期格式

写完该映射类后,当启动 IDE 的时候 IDE 会帮我们编译, 会自动在 target/classes 下生成对应的实现类,可以查看其实现的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2019-07-17T21:00:35+0800",
comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_191 (Oracle Corporation)"
)
@Component
public class UserMapperImpl implements UserMapper { @Override
public UserRoleDto toUserRoleDto(User user) {
if ( user == null ) {
return null;
} UserRoleDto userRoleDto = new UserRoleDto(); String name = userRoleName( user );
if ( name != null ) {
userRoleDto.setRoleName( name );
}
userRoleDto.setUserAddr( user.getAddr() );
userRoleDto.setUserName( user.getName() );
userRoleDto.setUserId( user.getId() ); return userRoleDto;
} private String userRoleName(User user) {
if ( user == null ) {
return null;
}
Role role = user.getRole();
if ( role == null ) {
return null;
}
String name = role.getName();
if ( name == null ) {
return null;
}
return name;
}
}

5. 测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMapstructApplicationTests {
大专栏  Java实体映射工具MapStruct的使用
@Autowired
UserMapper userMapper; User user; Role role; @Before
public void before() {
// 模拟数据库数据
role = new Role(2L, "admin", "管理员哦");
user = new User(1L, "sgh", "China", role);
} @Test
public void contextLoads() {
System.out.println("----------------user---------------");
System.out.println(user);
UserRoleDto userRoleDto = userMapper.toUserRoleDto(user);
System.out.println("----------------touserDto--------------");
System.out.println(userRoleDto);
} }

运行结果

可以看到 user.role.name 字段成功映射到了 userRoleDto 的 roleName 字段上。

6. 使用实现类的实例进行转换

UserRoleMapper.java 类修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Mapper
public interface UserRoleMapper { // 获取该类自动生成的实现类的实例
UserRoleMapper INSTANCE = Mappers.getMapper(UserRoleMapper.class); @Mappings({
@Mapping(source = "id", target = "userId"),
@Mapping(source = "name", target = "userName"),
@Mapping(source = "addr", target = "userAddr"),
@Mapping(source = "role.name", target = "roleName"),
})
UserRoleDto toUserRoleDto(User user);
}

Mapper 的 componentModel 属性使用默认的 default (不写即为 default)

测试类修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMapstructApplicationTests {
User user; Role role; @Before
public void before() {
// 模拟数据库数据
role = new Role(2L, "admin", "管理员哦");
user = new User(1L, "sgh", "China", role);
} @Test
public void contextLoads() {
System.out.println("----------------user---------------");
System.out.println(user);
UserRoleMapper INSTANCE = UserRoleMapper.INSTANCE;
UserRoleDto userRoleDto = INSTANCE.toUserRoleDto(user);
System.out.println("----------------touserDto--------------");
System.out.println(userRoleDto);
} }

注意区别,因为映射类的 componentModel 不使用 spring , 因此不能通过 @Autowired 来自动注入,需要使用该类的实例来进行转换。

具体体现在以下两行代码中

UserRoleMapper INSTANCE = UserRoleMapper.INSTANCE;
UserRoleDto userRoleDto = INSTANCE.toUserRoleDto(user);

7. 多个参数

可以绑定多个对象的属性值到目标对象中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Mapper(componentModel = "spring")
public interface UserRoleMapper { // 使用单一对象
@Mappings({
@Mapping(source = "id", target = "userId"),
@Mapping(source = "name", target = "userName"),
@Mapping(source = "addr", target = "userAddr"),
@Mapping(source = "role.name", target = "roleName"),
})
UserRoleDto toUserRoleDto(User user); // 使用两个对象
@Mappings({
@Mapping(source = "user.id", target = "userId"),
@Mapping(source = "user.name", target = "userName"),
@Mapping(source = "user.addr", target = "userAddr"),
@Mapping(source = "role.name", target = "roleName"),
})
UserRoleDto toUserRoleDto(User user, Role role);
}

测试类修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMapstructApplicationTests { @Autowired
UserRoleMapper userRoleMapper; User user; Role role; @Before
public void before() {
// 模拟数据库数据
role = new Role(2L, "admin", "管理员哦");
user = new User(1L, "sgh", "China", role);
} @Test
public void contextLoads() {
System.out.println("----------------user---------------");
System.out.println(user);
UserRoleDto userRoleDto = userRoleMapper.toUserRoleDto(user, role);
System.out.println("----------------touserDto--------------");
System.out.println(userRoleDto);
} }

这里使用传两个参数进行属性映射,结果一致

项目代码: https://github.com/ShangguanHong/SpringBootDemo/tree/master/springboot-mapstruct

8. 参考资料

  1. MapStruct超级简单的学习笔记

Java实体映射工具MapStruct的使用的更多相关文章

  1. 推荐一个 Java 实体映射工具 MapStruct

    声明: 1.DO(业务实体对象),DTO(数据传输对象). 2.我的代码中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略这条就好. 在一个成熟的工程中,尤其是现在的分布式系统中,应用与应 ...

  2. 【工具库】Java实体映射工具MapStruct

    一.什么是MapStruct? MapStruct是用于代码中JavaBean对象之间的转换,例如DO转换为DTO,DTO转换为VO,或Entity转换为VO等场景,虽然Spring库和 Apache ...

  3. Java实体映射工具MapStruct使用详解

    1.序 通常在后端开发中经常不直接返回实体Entity类,经过处理转换返回前端,前端提交过来的对象也需要经过转换Entity实体才做存储:通常使用的BeanUtils.copyProperties方法 ...

  4. 在线数据库表(sql语句)生成java实体类工具

    相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设 ...

  5. Mybatis自动生成实体类和实体映射工具

    Mybatis Mysql生成实体类 用到的Lib包: mybatis-generator-core-1.3.2.jarmysql-connector-java-5.1.30.jar 1. 创建一个文 ...

  6. Dozer JAVA的POJO 映射工具

    Dozerhttp://www.manongjc.com/article/50949.html JAVA的映射工具 BeanUtils dozer的使用方法https://blog.csdn.net/ ...

  7. xml文档的解析并通过工具类实现java实体类的映射:XML工具-XmlUtil

    若有疑问,可以联系我本人微信:Y1141100952 声明:本文章为原稿,转载必须说明 本文章地址,否则一旦发现,必追究法律责任 1:本文章显示通过 XML工具-XmlUtil工具实现解析soap报文 ...

  8. MapStruct 映射工具

    # MapStruct 映射工具  本篇主要讲解MapStruct 一款映射工具,只需简单的定义一个Mapper接口,在编译期间,MapStruct将生成此接口的实现,据说MapStruct性能最高是 ...

  9. EF架构~AutoMapper对象映射工具简化了实体赋值的过程

    回到目录 AutoMapper是一个.NET的对象映射工具,一般地,我们进行面向服务的开发时,都会涉及到DTO的概念,即数据传输对象,而为了减少系统的负载,一般我们不会把整个表的字段作为传输的数据,而 ...

随机推荐

  1. Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-1

    1 更高级的算法牵扯到更多重的循环和复杂的计算,尤其是现在人工智能的算法尤其如此.有些历史知识的人能够了解到,人工智能的很多基本算法其实近百年之前就有了,但是当时的计算机技术达不到去实现这些算法的要求 ...

  2. 吴裕雄--天生自然 PYTHON3开发学习:面向对象

    class MyClass: """一个简单的类实例""" i = 12345 def f(self): return 'hello wor ...

  3. 第04项目:淘淘商城(SpringMVC+Spring+Mybatis)【第九天】(商品详情页面实现)

    https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040 ...

  4. British postal system to launch parcel postboxes

    1 单词 parcel n. 包裹 pilot n. 试行计划 2 句子 1400 of the new boxes will be installed at 30 locations across ...

  5. 解决ubuntu16.04启动时长时间陷入紫屏

    今天我的ubuntu系统进不去,一启动就陷入紫屏的死循环中,重装了两遍系统还是一样进不去,后来上网查找了各种解决办法,网上都说是显卡的问题,我也不懂什么意思.试了几种方法,终于解决了这个问题,在这里记 ...

  6. 爬虫笔记(二)——浏览器的模拟(Headers属性)

    有的时候,我们无法爬取一些网页,会出现403错误,因为这些网页为了防止别人恶意采集其信息所以进行了一些反爬虫的设置.那么如果我们向爬取这些网页的信息,应该怎么办呢? 可以设置一些Headers信息,模 ...

  7. auctex 11.86的墓志铭

    卸载了emacs23,在Ubuntu 软件中心搜索并安装了emacs24.3.把auctex11.86也卸载了(自然,在.emacs文件里也注释掉了它的加载路径,但是我不会删去那段代码的.让注释的那段 ...

  8. java中==和equals

    /** * @author zhaojiatao * @date 2018/7/19 */ public class equalsLearn { public static void main(Str ...

  9. 奇点云数据中台技术汇(三)| DataSimba系列之计算引擎篇

    随着移动互联网.云计算.物联网和大数据技术的广泛应用,现代社会已经迈入全新的大数据时代.数据的爆炸式增长以及价值的扩大化,将对企业未来的发展产生深远的影响,数据将成为企业的核心资产.如何处理大数据,挖 ...

  10. Linux文件与目录管理,常用命令总结

    绝对路径:  以根目录 / 开始的相对路径:  相对于当前路径的写法 $PATH:  可执行文件路径的变量(出现在该变量下的文件可以在系统的任何目录下都可以执行) 获取路径的文件名:    basen ...