MapStruct优雅的转换bean对象

日常开发中,我们常常需要将业务相关的各种PO,VO,DTO对象互相转换,比较常用的工具类就是 BeanUtil ,但是BeanUtil有两个问题:

  • 底层使用了反射,效率不高
  • 无法自定义转换规则,例如其中一个bean中的datetime是Date类型,而另一个bean中的datetime是String类型,这就无法转换过去了

这里我要推荐一个比较好用的bean转换工具:MapStruct

MapStruct用法

准备工作

创建maven项目,引入以下依赖

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.3.0.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.3.0.Final</version>
</dependency>

准备两个实体类 DogPODogVO ,为了偷懒,我用了lombok插件。

/**
 * VO类
 */
@Data
public class DogVO {
    private int id;

    private String name;

    private int weight;

    private Date birthday;
}
/**
 * PO类
 */
@Data
public class DogPO {
    private int id;

    private String name;

    private int weight;

    private Date birthday;
}

最普通的转换

完成以上准备之后,我们编写一个 DogConvertor 接口

@Mapper  //注意这里的注解是org.mapstruct.Mapper,不要引入错了,mybatis包也有个的@Mapper注解
public interface DogConvertor {
    DogConvertor INSTANCE = Mappers.getMapper(DogConvertor.class);

    /**
     * 将VO转为PO
     * @param vo
     * @return
     */
    DogPO voToPO(DogVO vo);
}

测试代码:

    public static void main(String[] args) {
        //创建一个VO类
        DogVO dogVO = new DogVO();
        dogVO.setId(1);
        dogVO.setName("旺财");
        dogVO.setWeight(20);
        dogVO.setBirthday(new Date());
        //将VO类转换为PO类,实际上就是创建一个PO类,并将VO类的属性值都拷贝过去
        DogPO dogPO = DogConvertor.INSTANCE.voToPO(dogVO);
        System.out.println(dogPO);
    }

输出结果
在这里插入图片描述
我们看到PO类的属性全都被赋值好了。
为啥我们只写了一个接口,没有写任何的转换逻辑,就可以自动将 DogVO 转换为 DogPO 呢?
找到编译后的字节码目录下,会看到一个Impl文件。
在这里插入图片描述
我们将这个Impl打开(使用Idea打开class文件会自动为我们反编译的)
在这里插入图片描述
这就很好理解了MapStruct在编译阶段会识别我们的接口,生成一个实现类,在实现类中,为我们实现了set逻辑例如,上面的例子中,给DogCovertor接口,生成了一个实现类DogCovertorImpl

属性名不同的转换

我们将 DogPO 中的 name 属性改为 dogName ,这样一来我们该如何将 DogVO 中的 name 属性转换到 dogName 上呢?MapStruct很贴心的为我们提供了 @Mapping 注解

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

    /**
     * 将VO转为PO
     * @param vo
     * @return
     */
    @Mapping(source = "name", target = "dogName")
    DogPO voToPO(DogVO vo);
}

##集合转换
如果我们想要将List<DogVO>转换为List<DogPO>,该怎么办呢。也很简单,只需在接口中写下面这样的方法就好

List<DogPO> voListToPOList(List<DogVO> vo);

测试代码

    public static void main(String[] args) {
        List<DogVO> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            DogVO dogVO = new DogVO();
            dogVO.setId(i);
            dogVO.setName("旺财" + i);
            dogVO.setWeight(20 + i);
            dogVO.setBirthday(new Date());
            list.add(dogVO);
        }

        List<DogPO> dogPOList = DogConvertor.INSTANCE.voListToPOList(list);
        System.out.println(dogPOList);
    }

在这里插入图片描述

属性类型不同

将DogPO的 birthday 改为 String 类型

@Data
public class DogPO {
    private int id;

    private String dogName;

    private int weight;

    private String birthday;
}
    @Mappings({
            @Mapping(source = "name", target = "dogName"),
            @Mapping(target = "birthday", expression = "java(cn.hutool.core.date.DateUtil.format(vo.getBirthday(), \"yyyy-MM-dd HH:mm:ss\"))")
    })
    DogPO voToPO(DogVO vo);

输出结果
在这里插入图片描述

多个bean合并为一个bean

在实际业务情况中,我们有时候会遇到将多个Bean转换为一个Bean的情况。我们知道狗子身上一定会有一条尾巴,我们创建一个 TailVO 类

@Data
@AllArgsConstructor
public class TailVO {
    private int length;
}

我们要将 TailVO 和 DogVO 合并为一个 DogPO ,在DogPO类中添加一个tailLength 属性

@Data
public class DogPO {
    private int id;

    private String dogName;

    private int weight;

    private String birthday;
    /**
     * 尾巴长度
     */
    private int tailLength;
}
    @Mappings({
            @Mapping(source = "vo.name", target = "dogName"), //由于多了一个参数,所以这里的必须要指定vo.name
            @Mapping(target = "birthday", expression = "java(cn.hutool.core.date.DateUtil.format(vo.getBirthday(), \"yyyy-MM-dd HH:mm:ss\"))"),
            @Mapping(source = "tailVO.length", target = "tailLength")
    })
    DogPO voToPO(DogVO vo, TailVO tailVO);

测试代码

    public static void main(String[] args) {
        DogVO dogVO = new DogVO();
        dogVO.setId(1);
        dogVO.setName("旺财");
        dogVO.setWeight(20);
        dogVO.setBirthday(new Date());

        TailVO tailVO = new TailVO(10);

        DogPO dogPO = DogConvertor.INSTANCE.voToPO(dogVO, tailVO);
        System.out.println(dogPO);
    }

输出结果
在这里插入图片描述

以上就是我在项目中使用MapStruct常用的一些用法,当然它本身还有很多高级的用法,大家可以自行去探索

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值