<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
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種:
(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; } }
使用@Mapper註解,宣告對映器,可以是介面,或者抽象類。
使用@Mapping註解,實現靈活的欄位對映,客製化對映的規則。
在宣告好轉換介面之後,MapStruct提供幾種方式獲取生成的Mapper對映器。
可以通過提供的Mappers工廠類,獲取指定的型別。
@Mapper public interface Assembler { //使用工廠方法獲取Mapper範例 Assembler INSTANCE = Mappers.getMapper(Assembler.class); ProductDTO toDTO(Product product); }
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; } }
對於同名同屬性的欄位,無需特別宣告指定,自動轉換。
對於不同名相同屬性的欄位,可以使用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; } }
支援把多個引數對映成一個型別,使用@Mapping指定即可。
@Mapper(componentModel = "spring") public interface Demo6Assembler { @Mapping(target = "productId", source = "product.productId") @Mapping(target = "desc", source = "detail.desc") ProductDTO toDetailDTO(Product product, ProductDetail detail); }
對映時除了生成新的新物件外,還支援現存物件的更新:
@Mapper(componentModel = "spring") public interface Demo6Assembler { @Mapping(target = "desc", source = "desc") void updateDTO(@MappingTarget ProductDTO productDTO, ProductDetail detail); }
如int、long、String,Integer、Long等。
@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; } }
某些型別的轉換,我們可以指定具體轉換的格式。
(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元") //BigDecimal轉換成字串 @Mapping(target = "stock", numberFormat = "#個") //字串轉換成int 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") //Date轉換成String @Mapping(target = "validTime", dateFormat = "yyyy-MM-dd HH:mm") //String轉換成Date 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; } }
(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; } public ProductDetailDTO toDetailDTO(ProductDetail detail) { if ( detail == null ) { ProductDetailDTO productDetailDTO = new ProductDetailDTO(); productDetailDTO.setDetailId( detail.getId() ); return productDetailDTO; }
(4)多層bean之間的轉換
@Mapping註解支援跨層級的屬性轉換,屬性可以在不同層級之間切換。
@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) { mappingTarget.setProductId( product.getProductId() ); }
MapStruct支援自定義轉換器,實現型別之間的轉換自定義的規則。
一個自定義對映器可以定義多個對映方法,匹配時,是以方法的入參和出參進行匹配的。如果繫結的對映中,存在多個相同的入參和出參方法,將會報錯。
如果多個入參或者出參方法存在繼承關係,將會匹配最具體的那一個方法。
@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; }
定義對映器:
@Component public class ImageFormater { public String format(List<String> images) { return String.join(",", 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; } }
自定義轉換器時,存在多個相同入參和出參的方法,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); }
可以使用@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); }
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; } }
使用MapStruct可以使用物件工廠來建立bean,同時也可以更新bean。
定義物件工廠:
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; } }
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; } }
當返回的結果型別存在繼承關係時,可以使用@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; } }
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提供了集中方式實現。
對於複雜的對映,允許使用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; } }
MapStruct允許使用裝飾器進行一些複雜對映,同時可以支援和Spring結合。
定義一個對映器,同時宣告繫結裝飾器:
@Mapper(componentModel = "spring") @DecoratedWith(Demo18AssemblerDecorator.class) //宣告繫結裝飾器 public interface Demo18Assembler { ProductDTO toDTO(Product product); }
定義裝飾器:
public abstract class Demo18AssemblerDecorator implements Demo18Assembler { @Autowired @Qualifier("delegate") //注入mapStruct生成的轉換器,原始的轉換器注入spring時,會使用delegate裝飾符 private Demo18Assembler assembler; //可以獲取spring的bean進行操作 @Autowired private StringUtils stringUtils; @Override public ProductDTO toDTO(Product product) { //呼叫MapStruct進行轉換 ProductDTO productDTO = assembler.toDTO(product); //自定義操作 stringUtils.join(product.getName(), "-", product.getTitle()); return productDTO; } }
生成裝飾器程式碼:
@Component @Primary //Primary修飾,方便使用時直接使用autowired注入 public class Demo18AssemblerImpl extends Demo18AssemblerDecorator implements Demo18Assembler { }
使用@BeforeMapping和@AfterMapping註解可以指定對映過程的的回撥方法,進行一些前置或者後置的操作。
前置回撥方法的執行時機是在對映方法開始時,後置方法是在對映完成return之前。
回撥方法可以直接定義在對映器內:
@Mapper(componentModel = "spring") public interface Demo19Assembler { ProductDTO toDTO(Product product); @BeforeMapping //前置執行 default ProductDTO toDTOBefore(Product product) { ProductDTO productDTO = new ProductDTO(); productDTO.setSales(9999); return productDTO; } @AfterMapping //後置執行 default void toDTOAfter(Product product, @MappingTarget ProductDTO productDTO) { productDTO.setViewName(product.getName() + "-" + product.getTitle()); } }
生成的實現程式碼如下:
@Component public class Demo19AssemblerImpl implements Demo19Assembler { @Override public ProductDTO toDTO(Product product) { ProductDTO target = toDTOBefore( product ); //前置 if ( target != null ) { return target; } if ( product == null ) { return null; } ProductDTO productDTO = new ProductDTO(); productDTO.setProductId( product.getProductId() ); toDTOAfter( product, productDTO ); //後置 return productDTO; } }
回撥方法與對映的方法的匹配規則:
(1)對映方法和回撥方法沒有強繫結的關係,是依靠引數型別來匹配對映方法與回撥方法的。對映方法的所有入參和出參型別,能覆蓋回撥方法的入參,就會呼叫對應的回撥方法,當要注意,如果回撥方法的入參是對映方法的出參型別,回撥方法中需要用@MappingTarget 指定,否則不會呼叫。
(2)回撥方法是void或者返回對映方法的出參型別才能匹配,但要注意,如果返回的是對映方法的出參型別,如果執行時返回不為null,則對映方法直接返回回撥方法執行結果,不會往後執行。
到此這篇關於Java中的MapStruct用法詳解的文章就介紹到這了,更多相關javaMapStruct用法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45