当前位置: 首页 > news >正文

mapstruct 简单实践笔记

mapstruct 简单实践笔记

简介

Java bean映射,简单的方法!

MapStruct是一个代码生成器,极大地简化了基于配置的约定的Java bean类型之间映射的实现。
生成的映射代码使用简单的方法调用,因此速度快、类型安全且易于理解。

文档

http://mapstruct.org/

http://mapstruct.org/documentation/dev/reference/html/

https://github.com/mapstruct/mapstruct-examples

实践

  1. 依赖
<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>
  1. 定义实体类

User.java

@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private Long id;

    private String name;

    private Integer age;

    private Date birthday;

    private LocalDate localDate;
}

UserVo.java

@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserVo {

    private Long id;

    private String name;

    private Integer age;
}
  1. 定义UserMapper类

格式为:

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserVo toUserVo(User user);
}
  1. 测试
@Test
public void test1() {
    User user = User.builder().id(100L).name("gozi").age(19).birthday(new Date()).build();
    UserVo vo = UserMapper.INSTANCE.toUserVo(user);
    System.out.println(vo);
}
  1. 时间转换

三种方式:

    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy.MM.dd")
    @Mapping(target = "day", expression = "java(morning.cat.util.DateFormat.formatDate(user.getBirthday()))")
    @Mapping(target = "day2", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(user.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))")
    UserVo2 toUserVo2(User user);

    default UserVo2 toUserVo3(User user) {
        return UserVo2.builder().id(user.getId()).birthday(new SimpleDateFormat("yyyy-MM-dd").format(user.getBirthday())).build();
    }

第一种:使用 @Mapping 注解的 dateFormat 属性
第二种:使用 @Mapping 注解的 expression 属性(借助外部的静态方法)
第三种:在接口内部使用 default 实现一个默认方法(较为麻烦)

多个转换条件

	@Mappings({
            @Mapping(source = "sales", target = "volume"),
            @Mapping(source = "couponStartTime", target = "couponStartTime", dateFormat = "yyyy.MM.dd"),
            @Mapping(source = "couponEndTime", target = "couponEndTime", dateFormat = "yyyy.MM.dd")
    })
    PartnerItemBoV2 toPartnerItemBoV2(PartnerItem item);
  1. 忽略字段
@Mapping(target = "id", ignore = true)
  1. 字段映射

源实体类与目标实体类字段名不一致时;

@Mapping(source = "name", target = "nameFor")
  1. List映射

List<UserVo> toUserVos(List<User> user);

解析

使用mapstruct框架,编写使用@Mapper注解UserMapper接口类后,在编译后会自动生成接口实现类target/generated-sources/annotations/morning/cat/mapstruct/UserMapperImpl.java

以下内容是mapstruct框架根据配置自动生成的代码:

package morning.cat.mapstruct;

import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import morning.cat.entity.User;
import morning.cat.vo.UserVo;
import morning.cat.vo.UserVo.UserVoBuilder;
import morning.cat.vo.UserVo2;
import morning.cat.vo.UserVo2.UserVo2Builder;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2019-03-24T14:17:03+0800",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
)
public class UserMapperImpl implements UserMapper {

    @Override
    public UserVo toUserVo(User user) {
        if ( user == null ) {
            return null;
        }

        UserVoBuilder userVo = UserVo.builder();

        userVo.id( user.getId() );
        userVo.name( user.getName() );
        userVo.age( user.getAge() );

        return userVo.build();
    }

    @Override
    public List<UserVo> toUserVos(List<User> user) {
        if ( user == null ) {
            return null;
        }

        List<UserVo> list = new ArrayList<UserVo>( user.size() );
        for ( User user1 : user ) {
            list.add( toUserVo( user1 ) );
        }

        return list;
    }

    @Override
    public UserVo2 toUserVo2(User user) {
        if ( user == null ) {
            return null;
        }

        UserVo2Builder userVo2 = UserVo2.builder();

        if ( user.getBirthday() != null ) {
            userVo2.birthday( new SimpleDateFormat( "yyyy.MM.dd" ).format( user.getBirthday() ) );
        }
        if ( user.getLocalDate() != null ) {
            userVo2.localDate( DateTimeFormatter.ofPattern( "yyyy.MM.dd" ).format( user.getLocalDate() ) );
        }
        userVo2.nameFor( user.getName() );
        userVo2.age( user.getAge() );

        userVo2.day2( org.apache.commons.lang3.time.DateFormatUtils.format(user.getBirthday(),"yyyy-MM-dd HH:mm:ss") );
        userVo2.day( morning.cat.util.DateFormat.formatDate(user.getBirthday()) );

        return userVo2.build();
    }
}

本文源码:git@github.com:morningcat2018/mapstruct-sample.git

与Spring配合使用

定义:设置@Mapper注解的componentModel值为spring
UserMapper及其实现交给Spring容器管理;

@Mapper(componentModel = "spring")
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserVo toUserVo(User user);
}

使用:直接使用@Autowired进行自动注入;

@Autowired
UserMapper userMapper;

注意:这种实践需要在Spring环境下使用;

更多内容

请参考官网文档:http://mapstruct.org/documentation/dev/reference/html/

网上资料:https://zhuanlan.zhihu.com/p/38103512

相关文章:

  • Spring Data JPA 中 @Query 默认不能使用 limit函数
  • 基于Spring 2.0的Web应用设计
  • Spring MVC 官网文档阅读笔记(一)
  • oracle 连接 sqlserver
  • 关于jdk和java规范
  • 工作流入门(基础概念篇)
  • AspectJ 简介
  • 三亚之行
  • redis 学习笔记梳理
  • JavaScripte最经典和权威的教程(对象介绍)
  • 自定义注解的简单用法
  • FreeBSD-STABLE 居然是开发用的分支,我一直搞错了好多年...!
  • Spring Data JPA 在 SpringBoot 应用中的简单实践
  • 心与心的交流
  • SimpleDateFormat 线程不安全案例
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • angular2开源库收集
  • Fabric架构演变之路
  • JAVA 学习IO流
  • javascript面向对象之创建对象
  • jQuery(一)
  • Next.js之基础概念(二)
  • node-glob通配符
  • PAT A1017 优先队列
  • Spring Boot MyBatis配置多种数据库
  • vue 个人积累(使用工具,组件)
  • VUE es6技巧写法(持续更新中~~~)
  • Zepto.js源码学习之二
  • 产品三维模型在线预览
  • 代理模式
  • 给新手的新浪微博 SDK 集成教程【一】
  • 好的网址,关于.net 4.0 ,vs 2010
  • 看域名解析域名安全对SEO的影响
  • 码农张的Bug人生 - 见面之礼
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • Java总结 - String - 这篇请使劲喷我
  • MPAndroidChart 教程:Y轴 YAxis
  • 阿里云ACE认证之理解CDN技术
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • ${ }的特别功能
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (多级缓存)多级缓存
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (三)docker:Dockerfile构建容器运行jar包
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • .mysql secret在哪_MySQL如何使用索引
  • .Net CF下精确的计时器