MapStruct 使用指南

Spring的BeanUtils.copyProperties()与MapStruct 都是浅拷贝,BeanUtils.copyProperties()底层使用的是反射拷贝,而MapStruct底层方法是使用get(),set()拷贝,故速度比Spring的copy要快上不少

与Spring.BeanUtils.copy(source,target)对比结果图:

拷贝对象:TradeOrder 10 - 20 个有值字段进行拷贝

从图上来看,100000次拷贝速度,set > mapStruct > BeanCopier.copy > BeanUtils.copyProperties


使用步骤

1、引入依赖

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

⚠️:以下所有Mapper相关,都是MapStruct 包下的类(易与mybatis的Mapper混淆),便于区分可以在声明接口以其他标识作为后缀

2、调用方式

  2.1  Mapper工厂:声明一个接口,接口上加上@Mapper 注解 ,Mapper实例可以通过mapStruct 包下的Mappers类来获取,调用getMapper()方法

声明:

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

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


    TradeOrder convert(TradeOrder tradeOrder);

    Test2 convert(Test1 test1);

    TestDO convert(TestDO testDO);
}

    2.2 Spring 注入:需要在声明的拷贝接口上的注解加上componentModel = "spring"的参数(@Mapper(componentModel = "spring")),即可注册为Spring Bean对象,使用的时候注入使用即可

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

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


    TradeOrder convert(TradeOrder tradeOrder);

    Test2 convert(Test1 test1);

    TestDO convert(TestDO testDO);
}

3、基本原理:被@Mapper声明的接口,在编译期会生成impl文件,该文件的内容为声明方法的拷贝,内部都是使用get()/set()方法实现

        例:声明方法TradeOredr copyTradeOrderSelf(TradeOrder tradeOrder);

入参就是拷贝对象(等效于BeanUtils.copyProperties中 source),返回参数为拷贝后对象(等效于BeanUtils.copyProperties中 target

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.xcode.server.common.mapstruct;

import com.xcode.server.common.base.TestDO;
import com.xcode.server.common.base.TradeOrder;
import com.xcode.server.entity.ProductDO;
import com.xcode.server.entity.Test1;
import com.xcode.server.entity.Test2;
import java.util.ArrayList;
import java.util.List;

public class MapStructMapperImpl implements MapStructMapper {
    public MapStructMapperImpl() {
    }

    public TradeOrder convert(TradeOrder tradeOrder) {
        if (tradeOrder == null) {
            return null;
        } else {
            TradeOrder tradeOrder1 = new TradeOrder();
            tradeOrder1.setId(tradeOrder.getId());
            tradeOrder1.setTradeId(tradeOrder.getTradeId());
            tradeOrder1.setSourceTradeId(tradeOrder.getSourceTradeId());
            tradeOrder1.setTradeNo(tradeOrder.getTradeNo());
            tradeOrder1.setTradeFrom(tradeOrder.getTradeFrom());
            tradeOrder1.setTradeStatus(tradeOrder.getTradeStatus());
            tradeOrder1.setProcessStatus(tradeOrder.getProcessStatus());
            tradeOrder1.setTradeTime(tradeOrder.getTradeTime());
            tradeOrder1.setPayTime(tradeOrder.getPayTime());
            tradeOrder1.setAuditTime(tradeOrder.getAuditTime());
            tradeOrder1.setReviewTime(tradeOrder.getReviewTime());
            tradeOrder1.setNotifyPickTime(tradeOrder.getNotifyPickTime());
            tradeOrder1.setConsignTime(tradeOrder.getConsignTime());
            tradeOrder1.setConfirmTime(tradeOrder.getConfirmTime());
            tradeOrder1.setOrderNo(tradeOrder.getOrderNo());
            tradeOrder1.setShopId(tradeOrder.getShopId());
            tradeOrder1.setShopName(tradeOrder.getShopName());
            tradeOrder1.setCompanyId(tradeOrder.getCompanyId());
            tradeOrder1.setCompanyName(tradeOrder.getCompanyName());
            tradeOrder1.setDepartId(tradeOrder.getDepartId());
            tradeOrder1.setDepartName(tradeOrder.getDepartName());
            tradeOrder1.setWarehouseId(tradeOrder.getWarehouseId());
            tradeOrder1.setWarehouseName(tradeOrder.getWarehouseName());
            tradeOrder1.setLogisticId(tradeOrder.getLogisticId());
            tradeOrder1.setLogisticName(tradeOrder.getLogisticName());
            tradeOrder1.setLogisticType(tradeOrder.getLogisticType());
            tradeOrder1.setMainPostid(tradeOrder.getMainPostid());
            tradeOrder1.setTradeType(tradeOrder.getTradeType());
            tradeOrder1.setTotalFee(tradeOrder.getTotalFee());
            tradeOrder1.setTaxFee(tradeOrder.getTaxFee());
            tradeOrder1.setReceivedPostFee(tradeOrder.getReceivedPostFee());
            tradeOrder1.setDiscountFee(tradeOrder.getDiscountFee());
            tradeOrder1.setPayment(tradeOrder.getPayment());
            tradeOrder1.setCouponFee(tradeOrder.getCouponFee());
            tradeOrder1.setReceivedTotal(tradeOrder.getReceivedTotal());
            tradeOrder1.setPostFee(tradeOrder.getPostFee());
            tradeOrder1.setOtherFee(tradeOrder.getOtherFee());
            tradeOrder1.setIsMultiChargeType(tradeOrder.getIsMultiChargeType());
            tradeOrder1.setChargeType(tradeOrder.getChargeType());
            tradeOrder1.setChargeCurrency(tradeOrder.getChargeCurrency());
            tradeOrder1.setChargeAccount(tradeOrder.getChargeAccount());
            tradeOrder1.setAccountName(tradeOrder.getAccountName());
            tradeOrder1.setPayType(tradeOrder.getPayType());
            tradeOrder1.setPayAccount(tradeOrder.getPayAccount());
            tradeOrder1.setPayNo(tradeOrder.getPayNo());
            tradeOrder1.setSellerMemo(tradeOrder.getSellerMemo());
            tradeOrder1.setBuyerMemo(tradeOrder.getBuyerMemo());
            tradeOrder1.setAppendMemo(tradeOrder.getAppendMemo());
            tradeOrder1.setRegister(tradeOrder.getRegister());
            tradeOrder1.setRegisterId(tradeOrder.getRegisterId());
            tradeOrder1.setSellerId(tradeOrder.getSellerId());
            tradeOrder1.setSeller(tradeOrder.getSeller());
            tradeOrder1.setAuditorId(tradeOrder.getAuditorId());
            tradeOrder1.setAuditor(tradeOrder.getAuditor());
            tradeOrder1.setReviewerId(tradeOrder.getReviewerId());
            tradeOrder1.setReviewer(tradeOrder.getReviewer());
            tradeOrder1.setEstimateWeight(tradeOrder.getEstimateWeight());
            tradeOrder1.setPackageWeight(tradeOrder.getPackageWeight());
            tradeOrder1.setTradeCount(tradeOrder.getTradeCount());
            tradeOrder1.setGoodsTypeCount(tradeOrder.getGoodsTypeCount());
            tradeOrder1.setIsDeliveryBatch(tradeOrder.getIsDeliveryBatch());
            tradeOrder1.setIsFreeze(tradeOrder.getIsFreeze());
            tradeOrder1.setFreezeReason(tradeOrder.getFreezeReason());
            tradeOrder1.setIsAbnormal(tradeOrder.getIsAbnormal());
            tradeOrder1.setAbnormalDescription(tradeOrder.getAbnormalDescription());
            tradeOrder1.setGoodslist(tradeOrder.getGoodslist());
            tradeOrder1.setPrice(tradeOrder.getPrice());
            tradeOrder1.setIsDelete(tradeOrder.getIsDelete());
            tradeOrder1.setSettleStatus(tradeOrder.getSettleStatus());
            tradeOrder1.setGmtCreate(tradeOrder.getGmtCreate());
            tradeOrder1.setGmtModified(tradeOrder.getGmtModified());
            tradeOrder1.setStockoutNo(tradeOrder.getStockoutNo());
            tradeOrder1.setFlagIds(tradeOrder.getFlagIds());
            tradeOrder1.setSysFlagIds(tradeOrder.getSysFlagIds());
            tradeOrder1.setLastShipTime(tradeOrder.getLastShipTime());
            tradeOrder1.setPayStatus(tradeOrder.getPayStatus());
            tradeOrder1.setChargeCurrencyCode(tradeOrder.getChargeCurrencyCode());
            tradeOrder1.setChargeExchangeRate(tradeOrder.getChargeExchangeRate());
            tradeOrder1.setGrossProfit(tradeOrder.getGrossProfit());
            tradeOrder1.setEstimateVolume(tradeOrder.getEstimateVolume());
            tradeOrder1.setCancelReason(tradeOrder.getCancelReason());
            tradeOrder1.setCommision(tradeOrder.getCommision());
            tradeOrder1.setOnlineTradeNo(tradeOrder.getOnlineTradeNo());
            tradeOrder1.setPayDueDate(tradeOrder.getPayDueDate());
            tradeOrder1.setLocalExchangeRate(tradeOrder.getLocalExchangeRate());
            tradeOrder1.setLocalCurrencyCode(tradeOrder.getLocalCurrencyCode());
            tradeOrder1.setArriveTime(tradeOrder.getArriveTime());
            tradeOrder1.setIsManualCompleteDelivery(tradeOrder.getIsManualCompleteDelivery());
            tradeOrder1.setJmallAccountName(tradeOrder.getJmallAccountName());
            tradeOrder1.setCustomerPayment(tradeOrder.getCustomerPayment());
            tradeOrder1.setCustomerDiscountFee(tradeOrder.getCustomerDiscountFee());
            tradeOrder1.setCustomerPostFee(tradeOrder.getCustomerPostFee());
            tradeOrder1.setCustomerTotalFee(tradeOrder.getCustomerTotalFee());
            tradeOrder1.setLogisticStatus(tradeOrder.getLogisticStatus());
            tradeOrder1.setIsUploadMart(tradeOrder.getIsUploadMart());
            tradeOrder1.setExpectReachTime(tradeOrder.getExpectReachTime());
            tradeOrder1.setDistributeLimitation(tradeOrder.getDistributeLimitation());
            tradeOrder1.setCustomerPayNo(tradeOrder.getCustomerPayNo());
            tradeOrder1.setCustomerTaxFee(tradeOrder.getCustomerTaxFee());
            tradeOrder1.setCustomerShopId(tradeOrder.getCustomerShopId());
            tradeOrder1.setInsuredValue(tradeOrder.getInsuredValue());
            tradeOrder1.setDistributionStationId(tradeOrder.getDistributionStationId());
            tradeOrder1.setDistributionStation(tradeOrder.getDistributionStation());
            tradeOrder1.setPickupTime(tradeOrder.getPickupTime());
            tradeOrder1.setPickupTimeId(tradeOrder.getPickupTimeId());
            tradeOrder1.setMerchandiserId(tradeOrder.getMerchandiserId());
            tradeOrder1.setMerchandiser(tradeOrder.getMerchandiser());
            tradeOrder1.setSourceTradeType(tradeOrder.getSourceTradeType());
            tradeOrder1.setApiType(tradeOrder.getApiType());
            tradeOrder1.setSalesId(tradeOrder.getSalesId());
            tradeOrder1.setSalesName(tradeOrder.getSalesName());
            tradeOrder1.setPickUpTime(tradeOrder.getPickUpTime());
            tradeOrder1.setSigningTime(tradeOrder.getSigningTime());
            tradeOrder1.setWarehouseFee(tradeOrder.getWarehouseFee());
            tradeOrder1.setCompleteTime(tradeOrder.getCompleteTime());
            tradeOrder1.setMemberId(tradeOrder.getMemberId());
            tradeOrder1.setMemberName(tradeOrder.getMemberName());
            tradeOrder1.setInTransitTime(tradeOrder.getInTransitTime());
            tradeOrder1.setDeliveryingTime(tradeOrder.getDeliveryingTime());
            tradeOrder1.setTestDO(this.convert(tradeOrder.getTestDO()));
            return tradeOrder1;
        }
    }

    public Test2 convert(Test1 test1) {
        if (test1 == null) {
            return null;
        } else {
            Test2 test2 = new Test2();
            test2.setAsda(test1.getAsda());
            if (test1.getTrueStr() != null) {
                test2.setTrueStr(Boolean.parseBoolean(test1.getTrueStr()));
            }

            test2.setAaa(test1.isAaa());
            test2.setBbb(test1.getBbb());
            return test2;
        }
    }

    public TestDO convert(TestDO testDO) {
        if (testDO == null) {
            return null;
        } else {
            TestDO testDO1 = new TestDO();
            testDO1.setYes(testDO.isYes());
            testDO1.setName(testDO.getName());
            testDO1.setStock(testDO.getStock());
            testDO1.setTt(testDO.getTt());
            testDO1.setProductDO(testDO.getProductDO());
            testDO1.setIsDelete(testDO.getIsDelete());
            testDO1.setTrue(testDO.isTrue());
            List<ProductDO> list = testDO.getProductDOs();
            if (list != null) {
                testDO1.setProductDOs(new ArrayList(list));
            }

            return testDO1;
        }
    }
}

如果需要映射不同字段的:需要在Mapper接口方法上使用@Mapping(source = "fieldName", target = "targetName")即可,例:

@Mapping(source = "field2", target = "field1")
TradeOrder convert(TradeOrder tradeOrder);

⚠️需注意点:存在类型从大转到小会丢失精度问题,需要在方法上添加参数 typeConversionPolicy = ReportingPolicy.ERROR 

@Mapper(componentModel = "spring", typeConversionPolicy = ReportingPolicy.ERROR)
public interface MapStructCopyComponent {
}

这样在编译期间如果发现该种字段,会编译报错,如果一定要两个拷贝的对象进行编译成功,可以在具体方法上添加注解,忽略对象拷贝

@Mappings(
        {@Mapping(target = "strLong", ignore = true),
         @Mapping(target = "stock", ignore = true)}
)
TestDto convert11(TestDO testDO);

String <-> Integer/Long/Byte 等,会进行隐式转换,

例“a123“ 转成 Integer/Long/Byte 会直接报错

目前没有什么方法进行避免,转换错会抛出异常

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值