Java实体映射工具MapStruct的使用

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

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

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

下面进行 MapStruct 的使用。

2. 添加依赖

12345678910
<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

1234567
public class  {    private Long id;    private String name;    private String addr;    private Role role;}

Role.java

123456
public class Role {    private Long id;    private String name;    private String description;}

UserRoleDto.java

1234567
public class UserRoleDto {    private Long userId;    private String userName;    private String userAddr;    private String roleName;}

4. 编写映射类

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

1234567891011
@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 下生成对应的实现类,可以查看其实现的方法。

12345678910111213141516171819202122232425262728293031323334353637383940414243
@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)")@Componentpublic 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. 测试

12345678910111213141516171819202122232425262728
@RunWith(SpringRunner.class)@SpringBootTestpublic 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 类修改如下

1234567891011121314
@Mapperpublic 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)

测试类修改为

12345678910111213141516171819202122232425
@RunWith(SpringRunner.class)@SpringBootTestpublic 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. 多个参数

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

123456789101112131415161718192021
@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);}

测试类修改为

12345678910111213141516171819202122232425262728
@RunWith(SpringRunner.class)@SpringBootTestpublic 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超级简单的学习笔记

原文地址:https://www.cnblogs.com/lijianming180/p/12239924.html

时间: 2024-11-09 05:10:24

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

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

声明: 1.DO(业务实体对象),DTO(数据传输对象). 2.我的代码中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略这条就好. 在一个成熟的工程中,尤其是现在的分布式系统中,应用与应用之间,还有单独的应用细分模块之后,DO 一般不会让外部依赖,这时候需要在提供对外接口的模块里放 DTO 用于对象传输,也即是 DO 对象对内,DTO对象对外,DTO 可以根据业务需要变更,并不需要映射 DO 的全部属性. 这种 对象与对象之间的互相转换,就需要有一个专门用来解决转换问题的工具,毕竟

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

相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设计的一定是数据库表结构,而不是实体类.实体类仅仅是对底层数据结构的有损压缩,它仅仅是数据载体,不具备数据归档能力. 因此,很多时候,我们需要将原始的SQL建表语句转换成java实体类,这项工作看似简单,但若人工完成,工作量也是相当可观的,而且难免会出现差错. 到目前为止,笔者还没有发现比较靠谱的此类

在线数据库表(sql语句)生成java实体类工具 - 参考手册

SQL建表语句 说明 格式良好的SQL建表语句,可以是直接从PowerDesigner.Navicat等工具中导出SQL建表语句.所谓格式良好,是指建表指令与表名必须在一行,字段名称.类型.注释必须在一行,因为这个工具是用正则实现的,并不是语法解析器,当然,以后有时间的话,会改进成解析器. 举例 -- ---------------------------- -- Table structure for t_activity -- ---------------------------- DRO

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

Mybatis Mysql生成实体类 用到的Lib包: mybatis-generator-core-1.3.2.jarmysql-connector-java-5.1.30.jar 1. 创建一个文件generator.properties, 主要用于配置相关路径和数据库信息. #工程src路径 project = D:/project/ #工程存放mapper.xml路径 resource = D:/project/ #指定数据连接驱动jar地址 classPath=D:/project/m

MapStruct 映射工具

# MapStruct 映射工具  本篇主要讲解MapStruct 一款映射工具,只需简单的定义一个Mapper接口,在编译期间,MapStruct将生成此接口的实现,据说MapStruct性能最高是Spring的CopyProperties的10倍,与手工编写映射代码相比,MapStruct通过生成繁琐且易于编写的代码来节省时间.遵循约定优于配置方法,MapStruct使用合理的默认值,但在配置或实现特殊行为时会采取措施. ###  1.引入MapStruct的依赖 org.mapstruct

java 实体对象与Map之间的转换工具类(自己还没看)

java实体对象与Map之间的转换工具类 import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class EntityUtils { /** * 实体类转Map * @param object * @return */ public static Map<String, Object> entityToMap(Object object) { Map<String,

Json数据生成Java实体工具

S1.Json2Java根据 JSon 数据自动生成对应的 Java 实体类,还支持 Parcel.Gson Annotations 对应代码自动生成.期待后续的提取父类以及多 url 构建整个工程的功能项目地址:https://github.com/jonfhancock/JsonToJava在线演示:http://jsontojava.appspot.com/ S2.jsonschema2pojo根据 Json 内容生成 java 对象,支持 jackjson 和 gson项目地址:http

利用在线工具根据JSon数据自动生成对应的Java实体类

如果你希望根据JSon数据自动生成对应的Java实体类,并且希望能进行变量的重命名,那么“JSON To Java”一定适合你.(下面的地址需要FQ) https://jsontojava.appspot.com/ 简单快速有效,适合追求效率的你.

Java微信公众号开发-外网映射工具配置

一.开发环境准备 1.一个微信公众号 2.外网映射工具(开发调试)如花生壳.ngrok工具 注:与微信对接的URL要具备以下条件a:在公网上能够访问 b:端口只支持80端口 这里使用ngrok.cc: ngrok.cc它的服务基于ngrok实现,防止ngrok官网被墙不能访问,把服务器架设在了香港,不仅大大加快了大家的访问速度,还不怕被墙了,而且完全免费.官网地址::http://ngrok.cc/ 搭建步骤: 1.下载客户端 下载链接:http://www.ngrok.cc/index.php