ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

那些你不知道的MapStruct用法——Mapstruct自定义映射

2021-11-21 20:02:13  阅读:545  来源: 互联网

标签:自定义 映射 person MapStruct PersonMapper Mapstruct delegate 方法 public


那些你不知道的MapStruct用法——Mapstruct自定义映射

前言

mapStruct是一个很好用的字段映射工具,可以帮你自动生成代码完成字段映射。但有时需要在某些映射方法之前或之后应用自定义逻辑。
比如我们从数据库查出来的sex字段是一个数字 0,1,我们需要将其转换为男,女 放入Dto传给前端。我之前的做法是,mapstruct做完映射之后再进行字段转换。但这样会让service层增加很多set get 代码,如果是集合之间进行转换,我们还需遍历一次。
MapStruct 提供了两种方法:装饰器允许对特定映射方法进行类型安全的定制,以及映射前和映射后生命周期方法允许对给定源或目标类型的映射方法进行通用定制,可以很好的帮助我们解决该问题

使用装饰器映射

mapstruct使用装饰器模式,对其映射后的结果做附加操作。

使用装饰器需要将装饰器应用于映射器类,使用@DecorateWith指定装饰器类

@Mapper
@DecoratedWith(PersonMapperDecorator.class)
public interface PersonMapper {

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

    PersonDto personToPersonDto(Person person);

    AddressDto addressToAddressDto(Address address);
}

装饰器类必须实现映射器接口,可以声明为一个抽象类,只实现那些想要映射的方法。

使用示例

public abstract class PersonMapperDecorator implements PersonMapper {

    private final PersonMapper delegate;

    public PersonMapperDecorator(PersonMapper delegate) {
        this.delegate = delegate;
    }

    @Override
    public PersonDto personToPersonDto(Person person) {
        PersonDto dto = delegate.personToPersonDto( person );
        dto.setFullName( person.getFirstName() + " " + person.getLastName() );
        return dto;
    }
}

映射器使用Spring注入

如果你的映射类使用了Spring容器,那么在装饰器类,你需要用@Qualifier(“delegate”)来注入该映射类
(名字必须是delegate,因为生成的实现类bean名称默认就是这个)

public abstract class PersonMapperDecorator implements PersonMapper {

     @Autowired
     @Qualifier("delegate")
     private PersonMapper delegate;

     @Override
     public PersonDto personToPersonDto(Person person) {
         PersonDto dto = delegate.personToPersonDto( person );
         dto.setName( person.getFirstName() + " " + person.getLastName() );

         return dto;
     }
 }

装饰器类不需要我们去调用,使用的时候我们还像以前那样调用映射类就行。(建议使用构造器注入bean)

@Autowired
private PersonMapper personMapper;

public PersonDto  getPersonInfo(Long personId) {
	Person person = personDao.queryPerson(personId);
	return personMapper.personToPersonDto(person);
}

使用映射前和映射后方法进行映射定制

在自定义映射器时,装饰器可能并不总是满足需求。
例如,如果你不仅需要对特定的几个方法执行自定义映射,还需要对映射特定超类型的所有方法执行自定义内容,
在这种情况下,你可以使用在映射开始之前或映射完成之后调用的回调方法.

使用示例

@Mapper
public abstract class VehicleMapper {

    @BeforeMapping
    protected void flushEntity(AbstractVehicle vehicle) {
        // 可以在mapper类做映射前做一些操作
    }

    @AfterMapping
    protected void fillTank(AbstractVehicle vehicle, @MappingTarget AbstractVehicleDto result) {
        result.fuelUp( new Fuel( vehicle.getTankCapacity(), vehicle.getFuelType() ) );
    }

    public abstract CarDto toCarDto(Car car);
}

//mapper自动生成的代码
public class VehicleMapperImpl extends VehicleMapper {

    public CarDto toCarDto(Car car) {
        flushEntity( car );

        if ( car == null ) {
            return null;
        }

        CarDto carDto = new CarDto();

        fillTank( car, carDto );

        return carDto;
    }
}

@BeforeMapping@AfterMapping注释的方法,如果有参数,则只有在方法

  1. 法的返回类型(非void)可分配给映射方法的返回类型
  2. 所有参数都可以由映射的源或目标参数分配时,才会生成方法调用方法:

(有点绕,用上边的例子解释一下)

上面@BeforeMapping注释的 flushEntity方法的参数是AbstractVehicle类型, toCarDto 中的参数Car 就是该类型的子类,能传进去,就会生成该方法。

而上边@AfterMapping注释的方法有两个参数,可以看到一个加有@MappingTarget注解,意思是映射目标,而toCarDto 的映射目标类就是CarDto 他是AbstractVehicleDto的子类,达到可分配的条件,生成该方法。

上述方法不用满足第一个条件,因为他们返回值为null,
如果@BeforeMapping@AfterMapping注释的方法返回值不为null,则必须也有参数可分配才能生成。

调用顺序

方法调用的顺序主要由它们的变体决定:

@BeforeMapping@MappingTarget 在对源参数进行任何空检查和构造新的目标 bean 之前调用没有参数的方法。

@BeforeMapping@MappingTarget在构造新的目标 bean 后调用带有参数的方法。

@AfterMapping在最后一条return语句之前的映射方法的末尾调用方法。

标签:自定义,映射,person,MapStruct,PersonMapper,Mapstruct,delegate,方法,public
来源: https://blog.csdn.net/qq_45473439/article/details/121457329

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有