mapstruct学习

 

一、可使用的业务场景

相信很多同学在编码过程中会遇到从数据库查询A对象的集合数据,然后遍历A对象集合,然后封装到B数据集合中,然后返回B数据集合给调用者。

如:

List<A> listA = getListA();    //调用数据库查询数据

for(A a :listA){

    B b = new B();

    b.setName(a.getName());

    list.add(b);

}

在这个过程中,其实是没有什么难度的,就是遍历设置数据,当对象属性多的时候,设置的更加麻烦,今天就跟大家一起来学习mapstruct,看是如何解决这一问题,

在一个成熟可维护的工程中,细分模块后,domian工程最好不要被其他工程依赖,但是实体类一般存于domain之中,这样其他工程想获取实体类数据时就需要在各自工程写model,自定义model可以根据自身业务需要而并不需要映射整个实体属性。

二、什么是MapStruct

MapStruct 就是这样的一个属性映射工具,只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。MapStruct官网地址: http://mapstruct.org/

三、maven引入

<dependencies>
            <dependency>
                 <groupId>org.mapstruct</groupId>
                 <artifactId>mapstruct</artifactId>
                 <version>${mapstruct.version}</version>
                 <scope>compile</scope>
             </dependency>
             <dependency>
                 <groupId>org.mapstruct</groupId>
                 <artifactId>mapstruct-processor</artifactId>
                 <version>${mapstruct.version}</version>
                 <scope>compile</scope>
             </dependency>
                   <!-- other dependencies -->
         </dependencies>

四、具体使用实例

新建三个对象Car,CarTwo,CarVo(最终需要得到的对象)

import lombok.Data;

/**
 * @ClassName: Car
 * @Author: tanp
 * @Date: 2020/3/31 11:34
 */
@Data
public class Car {
    private String name;
    private String price;
    private String type;
    private String region;

}

 

import lombok.Data;

/**
 * @ClassName: CarTwo
 * @Author: tanp
 * @Date: 2020/3/31 14:55
 */
@Data
public class CarTwo {
    private String sign;
}
import lombok.Data;

/**
 * @ClassName: CarType
 * @Author: tanp
 * @Date: 2020/3/31 11:38
 */
@Data
public class CarVo {
    private String name;
    private String price;
    private String type;
    private String country;
    private String sign;

}

新建一个接口import org.mapstruct.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

/**
* @ClassName: CarShow
* @Author: tanp
* @Date: 2020/3/31 11:43
*/
@Mapper(componentModel = "spring") //集成spring的写法
@Component
public interface CarShow {
List<CarVo> showVo(List<Car> cars);

CarVo shwoOneCarVo(Car car, CarTwo carTwo);
}

编写代码完成后,编译下代码,这时会自动生成以下接口实现类,代码如下

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-03-31T14:59:17+0800",
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_162 (Oracle Corporation)"
)
@Component
public class CarShowImpl implements CarShow {

    @Override
    public List<CarVo> showVo(List<Car> cars) {
        if ( cars == null ) {
            return null;
        }

        List<CarVo> list = new ArrayList<CarVo>( cars.size() );
        for ( Car car : cars ) {
            list.add( carToCarVo( car ) );
        }

        return list;
    }

    @Override
    public CarVo shwoOneCarVo(Car car, CarTwo carTwo) {
        if ( car == null && carTwo == null ) {
            return null;
        }

        CarVo carVo = new CarVo();

        if ( car != null ) {
            carVo.setName( car.getName() );
            carVo.setPrice( car.getPrice() );
            carVo.setType( car.getType() );
        }
        if ( carTwo != null ) {
            carVo.setSign( carTwo.getSign() );
        }

        return carVo;
    }

    protected CarVo carToCarVo(Car car) {
        if ( car == null ) {
            return null;
        }

        CarVo carVo = new CarVo();

        carVo.setName( car.getName() );
        carVo.setPrice( car.getPrice() );
        carVo.setType( car.getType() );

        return carVo;
    }
}

 

五、知识点分析

1.实现类是自己生成的,前提是pom文件中引入mapstruct,然后在接口处引入了@Mapper(componentModel = "spring") 注解

2.看showVo方法,可以看到Car类中的region属性,并没有在CarVo设置到,而除region之外的其他属性在CarShowImp中都进行了设置,说明属性名相同直接设置,属性名不匹配的,如CarVo中的country属性,并没有被设置,所以在返回CarVo时,属性值设置为空,在本例中也就是country为空。当然也存在让属性名不同的属性互相设置,如把Car中的region属性的值,设置给CarVo中的country属性值,但是本人不推荐这种用法,所以这里没有详细讲解

3.查看shwoOneCarVo方法,可以看到是将两个实体属性的值设置到一个实体中,说明MapStruct 可以将几种类型的对象映射为另外一种类型

六、MapStruct 注解的关键词

@Mapper 只有在接口加上这个注解, MapStruct 才会去实现该接口
    @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个
    default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
    spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
@Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    source:源属性
    target:目标属性
    dateFormat:String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat              的日期格式
    ignore: 忽略这个字段
@Mappings:配置多个@Mapping
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MapStruct和BeanUtils是Java中常用的对象映射工具,它们都可以用于将一个对象的值映射到另一个对象上。以下是它们的优缺点: MapStruct的优点: 1. 性能优秀:MapStruct在编译期间生成映射代码,相比运行时的反射机制,具有更好的性能表现。 2. 类型安全:MapStruct在编译期间进行类型检查,避免了在运行时可能出现的类型转换错误。 3. 易于使用:MapStruct通过注解配置简单明了,生成的映射代码也易于理解和维护。 MapStruct的缺点: 1. 学习曲线较陡:对于初学者来说,需要一定时间去了解和掌握MapStruct的使用方式和配置方式。 2. 配置复杂:对于复杂的映射场景,可能需要编写自定义的转换器或者使用复杂的配置方式。 BeanUtils的优点: 1. 简单易用:BeanUtils提供了简单的API,易于学习和使用。 2. 动态性:BeanUtils使用反射机制,在运行时可以动态地进行属性复制。 BeanUtils的缺点: 1. 性能较差:由于使用了反射机制,BeanUtils在属性复制过程中性能相对较低,特别是处理大量对象时会有明显的性能损耗。 2. 不支持类型安全:BeanUtils在属性复制时没有类型检查,容易出现类型转换错误。 综上所述,MapStruct在性能和类型安全方面具有优势,适用于需要高性能和类型安全的场景。而BeanUtils则更适用于简单的属性复制场景,对于性能要求不高且不涉及复杂类型转换的情况下使用较为方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值