MapStruct用法

Posted gotten

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MapStruct用法相关的知识,希望对你有一定的参考价值。

 

1 MapStruct配置

        MapStuct的使用非常简单,把对应的jar包引入即可。

<properties>
    <mapstruct.version>1.3.1.Final</mapstruct.version>
</properties>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${mapstruct.version}</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${mapstruct.version}</version>
</dependency>

2 原理&性能 

2.1 实现原理    

        对象拷贝工具实现上一般分为2种:

       (1) 在运行时,通过反射调用set/get方法或者直接对成员变量进行赋值。

       (2)在编译期,动态生成调用get/set方法赋值的代码,直接生成对应的class文件。

       MapStrut属于第二种,在编译期间消耗少许的时间,换取运行时的高性能。

       接口声明:

@Mapper
public interface ProductAssembler {
    SkuDTO toDTO(Sku sku);
}

 

        编辑生成的class反编译 

public class ProductAssemblerImpl implements ProductAssembler {
    @Override
    public SkuDTO toDTO(Sku sku) {
        if ( sku == null ) {
            return null;
        }
        SkuDTO skuDTO = new SkuDTO();
        skuDTO.setSkuId( sku.getSkuId() );
        return skuDTO;
    }
}  

2.2 性能对比

        技术图片

3 使用方法

        使用Mapper注解,声明使用MapStruct实现的接口;

        使用Mapping注解,实现灵活的字段映射

3.1 转换器的检索

        在声明好转换接口之后,MapStruct提供几种方式获取生成的Mapper实现。

3.1.1 使用Mappers工厂获取

        可以通过提供的Mappers工厂类,获取指定的类型。

@Mapper
public interface Assembler {
    //使用工厂方法获取Mapper实例
    Assembler INSTANCE = Mappers.getMapper(Assembler.class);
    ProductDTO toDTO(Product product);
}

3.1.2 通过依赖注入的方式获取

  MapStuct同时支持和其他框架结合,通过依赖注入的方式获取Mapper实例。目前支持spring和cdi。

@Mapper(componentModel = "spring")
public interface Assembler {
    ProductDTO toDTO(Product product);
}
@Component 
public class AssemblerImpl implements Assembler { @Override public ProductDTO toDTO(Product product) { if ( product == null ) { return null; } ProductDTO productDTO = new ProductDTO(); productDTO.setProductId( product.getProductId() ); return productDTO; } }

3.2 简单映射

        对于同名同属性的字段,无需特别声明指定,自动转换。

        对于不同名相同属性的字段,可以使用Mapping注解指定。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    private String productId;
    private String name;
}

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = -6780322740093464581L;
    private String productId;
    private String productName;
}

 

@Mapper(componentModel = "spring")
public interface Assembler {
    @Mapping(source = "name", target = "productName")
    ProductDTO toDTO(Product product);
}

 

@Component
public class AssemblerImpl implements Assembler {

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }

        ProductDTO productDTO = new ProductDTO();

        productDTO.setProductName( product.getName() );  //不同字段名映射
        productDTO.setProductId( product.getProductId() );

        return productDTO;
    }
}

3.3 数据类型转换

3.3.1 对于基本的数据类型会进行自动隐式的转换

        如int、long、String,Integer等。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    private String productId;
    private Long price;
}

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = -6780322740093464581L;
    private int productId;
    private String price;
}

 

@Mapper(componentModel = "spring")
public interface Assembler {
    ProductDTO toDTO(Product product);
}

 

@Component
public class AssemblerImpl implements Assembler {

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }

        ProductDTO productDTO = new ProductDTO();

        if ( product.getProductId() != null ) {
            //String自动转int
            productDTO.setProductId( Integer.parseInt( product.getProductId() ) );
        }
        if ( product.getPrice() != null ) {
            //Long转String
            productDTO.setPrice( String.valueOf( product.getPrice() ) );
        }

        return productDTO;
    }
}

 3.3.2 指定转换格式

        (1)对于基本数据类型与String之间的转换,可以使用 numberFormat 指定转换格式,使用的是java.text.DecimalFormat 实现。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    private String productId;
    private BigDecimal price;
    private String stock;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = -6780322740093464581L;
    private String productId;
    private String price;
    private Integer stock;
}
@Mapper(componentModel = "spring")
public interface Demo3Assembler {
    @Mapping(target = "price", numberFormat = "#.00元")
    @Mapping(target = "stock", numberFormat = "#个")
    ProductDTO toDTO(Product product);
}
@Component
public class Demo3AssemblerImpl implements Demo3Assembler {

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }

        ProductDTO productDTO = new ProductDTO();

        productDTO.setProductId( product.getProductId() );
        if ( product.getPrice() != null ) {
            //BigDecimal格式化成字符串
            productDTO.setPrice( createDecimalFormat( "#.00元" ).format( product.getPrice() ) );
        }
        try {
            if ( product.getStock() != null ) {
                 //字符串格式化为int
                productDTO.setStock( new DecimalFormat( "#个" ).parse( product.getStock() ).intValue() );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }

        return productDTO;
    }

    private DecimalFormat createDecimalFormat( String numberFormat ) {
        DecimalFormat df = new DecimalFormat( numberFormat );
        df.setParseBigDecimal( true );
        return df;
    }
}
@Test
public void test2() {
    com.gotten.study.mapstruct.demo3.Product  product = new com.gotten.study.mapstruct.demo3.Product ();
    product.setProductId("P001");
    product.setPrice(new BigDecimal("100"));
    product.setStock("1个");
    com.gotten.study.mapstruct.demo3.ProductDTO productDTO = demo3Assembler.toDTO(product);
    System.out.println("productDTO:" + JSON.toJSONString(productDTO));
}


productDTO:{"price":"100.00元","productId":"P001","stock":1}

  (2)Date和String之间的转换,可以通过dateFormat指定转换格式,使用的是SimpleDateFormat的实现。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
    private String productId;
    private Date saleTime;
    private String validTime;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = -6780322740093464581L;
    private String productId;
    private String saleTime;
    private Date validTime;
}
@Mapper(componentModel = "spring")
public interface Demo4Assembler {
    @Mapping(target = "saleTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "validTime", dateFormat = "yyyy-MM-dd HH:mm")
    ProductDTO toDTO(Product product);
}
@Component
public class Demo4AssemblerImpl implements Demo4Assembler {
    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = new ProductDTO();
        productDTO.setProductId( product.getProductId() );
        if ( product.getSaleTime() != null ) {
            productDTO.setSaleTime( new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( product.getSaleTime() ) ); //转换成String
        }
        try {
            if ( product.getValidTime() != null ) {
                productDTO.setValidTime( new SimpleDateFormat( "yyyy-MM-dd HH:mm" ).parse( product.getValidTime() ) ); //转换成Date
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        return productDTO;
    }
}

3.3.3 对象引用的映射

        (1)对应是相同类型的对象引用,直接简单的对引用进行拷贝。

        (2)如果类型相同,但是是集合类的引用,会创建一个新的集合,集合里面的所有引用进行拷贝。

@Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = new ProductDTO();
        productDTO.setProductId( product.getProductId() );
        List<Sku> list = product.getSkuList();
        if ( list != null ) {
            productDTO.setSkuList( new ArrayList<Sku>( list ) ); //创建新的集合,并对所有元素进行拷贝
        }

        return productDTO;
    }

 

  (3)对象的类型不同,会检查是否存在对应的映射方法或者默认的类型转换器,否则会尝试自动创建子映射方法。


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private String productId;
private ProductDetail productDetail;
}
 
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDetail {
private String id;
}
 

 


@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDTO implements Serializable {
private static final long serialVersionUID = 2184784038009791692L;
private String productId;
private ProductDetailDTO productDetail;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDetailDTO {
private String detailId;
}
@Mapper(componentModel = "spring")
public interface Demo6Assembler {
ProductDTO toDTO(Product product);

@Mapping(target = "detailId", source = "id")
ProductDetailDTO toDetailDTO(ProductDetail detail);
}

@Component
public class Demo6AssemblerImpl implements Demo6Assembler {

@Override
public ProductDTO toDTO(Product product) {
if ( product == null ) {
return null;
}
ProductDTO productDTO = new ProductDTO();
productDTO.setProductId( product.getProductId() );
productDTO.setProductDetail( toDetailDTO( product.getProductDetail() ) ); //查找使用存在的转换方法
return productDTO;
}

@Override
public ProductDetailDTO toDetailDTO(ProductDetail detail) {
if ( detail == null ) {
return null;
}
ProductDetailDTO productDetailDTO = new ProductDetailDTO();
productDetailDTO.setDetailId( detail.getId() );
return productDetailDTO;
}
}

 

  (3)嵌套bean的转换

    可以使用mapping声明嵌套bean转换的规则,mapstruct生成子映射方法时,会使用者声明的规则。同时支持跨层级的属性转换。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private String productId;
    private ProductDetail productDetail;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDetail {
    private String id;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = 2184784038009791692L;
    private String productId;
    private ProductDetailDTO productDetail;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDetailDTO {
    private String productId;
    private String detailId;
}
@Mapper(componentModel = "spring")
public interface Demo7Assembler {
    @Mapping(target = "productDetail.detailId", source = "productDetail.id") //声明productDetail下的属性转换规则
    @Mapping(target = "productDetail.productId", source = "productId") //跨层级的属性转换,把product层级的productId放到productDetail层级
    ProductDTO toDTO(Product product);
}
@Component
public class Demo7AssemblerImpl implements Demo7Assembler {

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = new ProductDTO();
        if ( product.getProductDetail() != null ) {
            if ( productDTO.getProductDetail() == null ) {
                productDTO.setProductDetail( new ProductDetailDTO() );
            }
            productDetailToProductDetailDTO( product.getProductDetail(), productDTO.getProductDetail() );
        }
        if ( productDTO.getProductDetail() == null ) {
            productDTO.setProductDetail( new ProductDetailDTO() );
        }
        productToProductDetailDTO( product, productDTO.getProductDetail() );
        productDTO.setProductId( product.getProductId() );
        return productDTO;
    }

  //detail的转换方法 protected void productDetailToProductDetailDTO(ProductDetail productDetail, ProductDetailDTO mappingTarget) { if ( productDetail == null ) { return; } mappingTarget.setDetailId( productDetail.getId() ); }
  //product转成detail(更新处理) protected void productToProductDetailDTO(Product product, ProductDetailDTO mappingTarget) { if ( product == null ) { return; } mappingTarget.setProductId( product.getProductId() ); } }

 3.3.4 自定义映射器

  MapStatuct支持自定义映射器,实现自定义类型之间的转换。

  一个自定义映射器可以定义多个映射方法,匹配时,是以方法的入参和出参进行匹配的。如果绑定的映射中,存在多个相同的入参和出参方法,将会报错。

  如果多个入参或者出参方法存在继承关系,将会匹配最具体的那一个方法。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    private String productId;
    private List<String> images;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDTO implements Serializable {
    private static final long serialVersionUID = 2184784038009791692L;
    private String productId;
    private String images;
}

 

@Mapper(componentModel = "spring", uses = ImageFormater.class)
public interface Demo8Assembler {
    ProductDTO toDTO(Product product);
}
@Component
public class Demo8AssemblerImpl implements Demo8Assembler {

    @Autowired
    private ImageFormater imageFormater;

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }

        ProductDTO productDTO = new ProductDTO();
        productDTO.setProductId( product.getProductId() );
     //调用自定义的映射器进行映射,把list转成string productDTO.setImages( imageFormater.format( product.getImages() ) ); return productDTO; } }

 3.3.5 使用限定符限定使用映射方法

  自定义映射器时,存在多个相同入参和出参的方法,报错是因为MapStruct无法选择使用哪个映射方法。但有时确实有这样的场景,这时可以使用限定符绑定每个属性转换时使用的映射方法。

  (1)限定符使用自定义注解实现。

  声明限定符:

import org.mapstruct.Qualifier;


//映射器上的限定符
@Qualifier //标记为限定符
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Formators {
}
//映射方法上的限定符
@Qualifier //标记为限定符
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface FormatImages {
}

//映射方法上的限定符
@Qualifier //标记为限定符
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface FormatDetails {
}

 

  绑定限定符到映射器的方法上面:

@Component
@Formators //绑定限定符
public class CusFormater {
@FormatImages //绑定限定符
public String formatImages(List<String> images) {
return String.join(",", images);
}
@FormatDetails //绑定限定符
public String formatDetails(List<String> images) {
return String.join(",", images);
}
}

  映射时,绑定限定符,定位映射方法:

@Mapper(componentModel = "spring", uses = CusFormater.class)
public interface Demo9Assembler {
    @Mapping(target = "images", qualifiedBy = FormatImages.class) //转换指定限定符,定位具体的映射方法
    @Mapping(target = "details", qualifiedBy = FormatDetails.class)//转换指定限定符,定位具体的映射方法
    ProductDTO toDTO(Product product);
}

 

@Component
public class Demo9AssemblerImpl implements Demo9Assembler {
    @Autowired
    private CusFormater cusFormater;

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = new ProductDTO();
        productDTO.setProductId( product.getProductId() );
        productDTO.setImages( cusFormater.formatImages( product.getImages() ) ); //定位方法
        productDTO.setDetails( cusFormater.formatDetails( product.getDetails() ) );
        return productDTO;
    }
}

 

  (2)基于named注解实现(推荐)

  除了使用自定义住注解的方法,还可以使用@Named注解实现限定符的绑定。

@Component
@Named("CusFormater")
public class CusFormater {
    //绑定限定符
    @Named("formatImages")
    public String formatImages(List<String> images) {
        return String.join(",", images);
    }
    //绑定限定符
    @Named("formatDetails")
    public String formatDetails(List<String> images) {
        return String.join(",", images);
    }
}

 

  使用时绑定:

@Mapper(componentModel = "spring", uses = CusFormater.class)
public interface Demo10Assembler {
    @Mapping(target = "images", qualifiedByName = "formatImages") //转换指定限定符,定位具体的映射方法
    @Mapping(target = "details", qualifiedByName = "formatDetails")//转换指定限定符,定位具体的映射方法
    ProductDTO toDTO(Product product);
}

 

3.4 Map的映射

  可以使用@MapMapping实现对key和value的分别映射:

@Mapper(componentModel = "spring")
public interface Demo11Assembler {
    @MapMapping(valueDateFormat = "yyyy-MM-dd HH:mm:ss")
    Map<String, String> toDTO(Map<Long, Date> map);
}

 

 

3.5 枚举值之间的转换

  MapStruct可以在多个枚举值之间转换,使用@ValueMapping注解。

public enum E1 {
    E1_1,
    E1_2,
    E1_3,
    ;
}

public enum E2 {
    E2_1,
    E2_2,
    E2_3,
    ;
}
@Mapper(componentModel = "spring")
public interface Demo11Assembler {
    @ValueMapping(target = "E1_1", source = "E2_1")
    @ValueMapping(target = "E1_2", source = "E2_2")
    @ValueMapping(target = MappingConstants.NULL, source = "E2_3") //转换成null
    E1 toDTO(E2 e2);
}

  生成代码:

@Component
public class Demo11AssemblerImpl implements Demo11Assembler {

    @Override
    public E1 toDTO(E2 e2) {
        if ( e2 == null ) {
            return null;
        }
        E1 e1;
        switch ( e2 ) {
            case E2_1: e1 = E1.E1_1;
            break;
            case E2_2: e1 = E1.E1_2;
            break;
            case E2_3: e1 = null;
            break;
            default: throw new IllegalArgumentException( "Unexpected enum constant: " + e2 );
        }
        return e1;
    }
}

 

 

3.6 定制Bean生成或者更新Bean

  使用MapStruct可以使用对象工厂来创建bean,同时也可以更新bean。

3.6.1 对象工厂

  定义对象工厂:

public class DTOFactory {
    public ProductDTO createDTO() {
        ProductDTO productDTO = new ProductDTO();
        productDTO.setStock(0);
        return productDTO;
    }
}

  使用对象工厂:

@Mapper(componentModel = "spring", uses = DTOFactory.class) //指定使用的对象工厂
public interface Demo13Assembler {
    ProductDTO toDTO(Product product);
}

  生成代码:

@Component
public class Demo13AssemblerImpl implements Demo13Assembler {

    @Autowired
    private DTOFactory dTOFactory;
    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = dTOFactory.createDTO(); //使用对象工厂创建对象
        productDTO.setProductId( product.getProductId() );
        return productDTO;
    }
}

 

3.6.2 更新对象

  某些场景下,我们只是需要对对象进行更新,可以把需要更新的对象作为方法参数传入,并且使用@MappingTarget指定。

@Mapper(componentModel = "spring")
public interface Demo14Assembler {
    void updateDTO(Product product, @MappingTarget ProductDTO productDTO);
}
@Component
public class Demo14AssemblerImpl implements Demo14Assembler {
    @Override
    public void updateDTO(Product product, ProductDTO productDTO) {
        if ( product == null ) {
            return;
        }
        productDTO.setProductId( product.getProductId() );
    }
}

3.7 使用表达式映射值

  对于复杂的映射,允许使用java表达式实现字段的映射。

  注意要导入使用到的类。

@Mapper(componentModel = "spring", imports = DecimalUtils.class) //导入java表达式使用的类
public interface Demo16Assembler {
    @Mapping(target = "price", expression = "java(product.getPrice1() + product.getPrice2())") //直接相加
    @Mapping(target = "price2", expression = "java(DecimalUtils.add(product.getPrice1(), product.getPrice2()))") //使用工具类处理
    ProductDTO toDTO(Product product);
}

 

  

@Component
public class Demo16AssemblerImpl implements Demo16Assembler {

    @Override
    public ProductDTO toDTO(Product product) {
        if ( product == null ) {
            return null;
        }
        ProductDTO productDTO = new ProductDTO();
        productDTO.setProductId( product.getProductId() );
        productDTO.setPrice( product.getPrice1() + product.getPrice2() );
        productDTO.setPrice2( DecimalUtils.add(product.getPrice1(), product.getPrice2()) );
        return productDTO;
    }
}

 

3.8 缺省值和常量

  MapStruct允许设置缺省值和常量,同时缺省值允许使用表达式。

  注意:使用缺省值,源字段必须存在,否则缺省值不生效,否则应该使用常量。

@Mapper(componentModel = "spring", imports = UUID.class)
public interface Demo15Assembler {
@Mapping(target = "productId", source = "productId", defaultValue = "0") //当product的productId为null,设置为0
@Mapping(target = "random", source = "random", defaultExpression = "java(UUID.randomUUID().toString())") //缺省设置随机数
@Mapping(target = "stock", constant = "0") //固定设置为0
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd", constant = "2020-05-30") //固定格式化设置为2020-05-30,
ProductDTO toDTO(Product product);
}

  

@Component
public class Demo15AssemblerImpl implements Demo15Assembler {

@Override
public ProductDTO toDTO(Product product) {
if ( product == null ) {
return null;
}
ProductDTO productDTO = new ProductDTO();

if ( product.getProductId() != null ) {
productDTO.setRandom( product.getProductId() );
}
else {
productDTO.setRandom( UUID.randomUUID().toString() );
}
if ( product.getProductId() != null ) {
productDTO.setProductId( product.getProductId() );
}
else {
productDTO.setProductId( "0" );
}

productDTO.setStock( 0 );
try {
productDTO.setCreateTime( new SimpleDateFormat( "yyyy-MM-dd" ).parse( "2020-05-30" ) );
}
catch ( ParseException e ) {
throw new RuntimeException( e );
}

return productDTO;
}
}

3.9 存在继承关系的结果处理

  当返回的结果类型存在继承关系时,可以使用 @BeanMapping注解指定真实返回的结果类型。

@Mapper(componentModel = "spring")
public interface Demo17Assembler {
    @BeanMapping(resultType = DogDTO.class) //指定返回的结果类型
    Animal toDTO(Dog dog);
}

  

@Component
public class Demo17AssemblerImpl implements Demo17Assembler {
    @Override
    public Animal toDTO(Dog dog) {
        if ( dog == null ) {
            return null;
        }
        DogDTO animal = new DogDTO();
        animal.setId( dog.getId() );
        return animal;
    }
}

3.10 映射关系继承

  MapStruct允许对映射关系进行继承,使用@InheritConfiguration标记当前方法继承其他映射方法的映射关系。会自动查找相同类型映射源、映射目标的方法进行继承,如果存在多个相同类型的方法,则需要手工指定。

@Mapper(componentModel = "spring")
public interface Demo18Assembler {
@Mapping(target = "productId", source = "id")
@Mapping(target = "detail", source = "detail1")
ProductDTO toDTO(Product product);

@Mapping(target = "productId", source = "id2")
@Mapping(target = "detail", source = "detail2")
ProductDTO toDTO2(Product product);

@InheritConfiguration(name = "toDTO") //对toDTO的映射关系进行继承
@Mapping(target = "detail", source = "detail2") //对继承的关系进行重写
void update(@MappingTarget ProductDTO productDTO, Product product);

}

 

        除了正向继承规则外,还可以进行规则逆向继承,从被继承方法的目标对象映射到源对象。

@Mapper(componentModel = "spring")
public interface Demo18Assembler {
@Mapping(target = "productId", source = "id")
@Mapping(target = "detail", source = "detail1")
ProductDTO toDTO(Product product);

@Mapping(target = "productId", source = "id2")
@Mapping(target = "detail", source = "detail2")
ProductDTO toDTO2(Product product);

@InheritInverseConfiguration(name = "toDTO") //对toDTO的映射关系进行逆继承
@Mapping(target = "detail2", source = "detail") //对逆向继承的关系进行重写
Product toEntity(ProductDTO dto);
}

 

以上是关于MapStruct用法的主要内容,如果未能解决你的问题,请参考以下文章

mapstruct的用法-dateFormat

mapstruct对象转换工具

MapStruct 映射工具

MapStruct代码生成器实现对象转换

MapStruct,降低无用代码的神器

c_cpp 加载源图像固定用法(代码片段,不全)