对象拷贝初识mapstruct及与lombok的配置

        项目中用到对象拷贝,做一个修改历史记录保存的功能,使用Spring AOP自定义注解实现修改记录的保存,历史记录表和业务表的字段差不多,保存的时候需要用到对象拷贝。下面是一些对象拷贝的工具,前3个都用过,这次想尝试一下新的mapstruct,喜新厌旧一波。

1. 对象拷贝常见的工具类

1.1 Apache 的BeanUtils的copyProperties方法

特点:浅拷贝,属性还是指向原本对象的引用。字段名称相同,类型不同无法进行赋值,基本类型字段和引用对象可以映射。

1.2 SpringUtils的copyProperties方法

特点:同Apache,效率比Apache高,参数的位置与Apache不同

1.3 序列化(JSON)

特点:深拷贝,性能低,耗时长(序列化-反序列化)。基本类和引用对象可以映射。字段名称相同,类型不同可以赋值。

1.4 MapStruct

特点:深拷贝,灵活(可自主配置字段映射关系),可以配置多对一映射关系。效率高,准确(编译器代码生成,源码就是get、set方法)。

2. MapStruct初次使用配置过程

2.1典型的常规操作,这里记录我配置过程中遇到的问题,仅供参考,可以不看,直接看后面的正确配置;

2.2决定要用,就先Bing了一把,大体一看内容还算完整,有配置,有测试,还有代码和源码,一看感觉不难,哐哐哐一顿配置,然后不出意外的报错了;

2.3我用的是公司封装的框架,耦合高,有几点和网上说的不一样:

一个是我的实体类有继承;

二个是我继承的实体类没有用lombok插件,我用了;

这两点对我造成了困扰,但是不影响使用MapStruct。

遇到的异常有:

一个是“No property named “XXX“ exists in source parameter(s). Did you mean news”;

No property named “XXX“ exists in source parameter(s). Did you mean news

一个是lombok插件的问题,提示java找不到符号(解决第一个问题过程中,越解决问题越严重);

2.4配置过程

一开始,导入maven依赖,根据网上的博文,注意lombok和mapstruct的版本,选择了同一个年份的版本。这里我用的是lombok插件,查看版本后选择的mapstruct版本,发布的年份一样,但是月份不一样,就配置上了。

然后就可以添加代码,写了Mapper和拷贝方法,就开始单元测试,问题来了,提示No property named “XXX“ exists in source parameter(s),虽然属性我可以点进去,但是就是报错。我怀疑是版本问题,就开始重新捣鼓版本,各种尝试,没解决。只好去官网,发现官网上的配置还添加了maven-compiler-plugin插件,我也加上,然而问题更严重了,冲突更厉害,直接影响我的lombok代码,改了3个d插的件版本,未解决,只能还原回去,确认就是版本问题。因为MapStruct原理类似于lombok,都是在编译期进行实现。只能继续看官网文档,最终配置成功。有问题找官网准没错。

3. MapStruct的正确配置,这里介绍maven方式

3.1项目pom文件添加依赖和plugins

<properties>
    <java.version>1.8</java.version>
    <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
    <org.projectlombok.version>1.18.26</org.projectlombok.version>
    <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${org.projectlombok.version}</version>
    <scope>provided</scope>
</dependency>



<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.11.0</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessorPaths>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${org.mapstruct.version}</version>
            </path>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${org.projectlombok.version}</version>
            </path>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-mapstruct-binding</artifactId>
                <version>${lombok-mapstruct-binding.version}</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

3.2编写Mapper,我这里就用官网的代码了

CarMapper.java

@Mapper

public interface CarMapper {

CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

@Mapping(source = "numberOfSeats", target = "seatCount")

CarDto carToCarDto(Car car);

}

Car.java

public class Car {

    private String make;

    private int numberOfSeats;

    private CarType type;

    //constructor, getters, setters etc.

}

CatDto.java

public class CarDto {

    private String make;

   private int seatCount;

    private String type;

    //constructor, getters, setters etc.

}

测试方法:

@Test

public void shouldMapCarToDto() {

    //given

    Car car = new Car( "Morris", 5, CarType.SEDAN );

    //when

    CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );

    //then

    assertThat( carDto ).isNotNull();

    assertThat( carDto.getMake() ).isEqualTo( "Morris" );

    assertThat( carDto.getSeatCount() ).isEqualTo( 5 );

    assertThat( carDto.getType() ).isEqualTo( "SEDAN" );

}

4.总结:初次使用,没啥经验总结,这个项目也是简单使用,如有机会再深入了解。

4.1 lombok版本和MapStruct版本可以不必严格保持时间上对应。我这里用的就是最新的MapStruct版本和我IDE中lombok的插件版本,并不冲突。

4.2 如果两个对象中变量命名一致可以不用配置@Mapping。

/**
     * 这个方法就是用于实现对象属性复制的方法
     *
     * @param xx 这个参数就是源对象,也就是需要被复制的对象
     * @return 返回的是目标对象,就是最终的结果对象
     * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
     */
    @Mappings({@Mapping(source = "id", target = "detailId")})

4.3有事找官网

官网:MapStruct – Java bean mappings, the easy way!

再不行找官网的例子:

 GitHub - mapstruct/mapstruct-examples: Examples for using MapStruct

4.4 maven-compiler-plugin插件的版本根据你自己需要选择,不影响。主要的是annotationProcessorPaths的配置,我参考的是官方例子里面的mapstruct-lombok

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值