欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中MapStruct復(fù)制對(duì)象的具體使用

 更新時(shí)間:2024年12月06日 10:50:33   作者:String、code  
MapStruct是一個(gè)用于Java的代碼生成器,可以自動(dòng)生成類型安全的Bean映射代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、前言

大家在開(kāi)發(fā)中,最讓人頭疼的就是:對(duì)象之間的拷貝,前端的VO和數(shù)據(jù)庫(kù)的Entity不一致!

性能最好的就是手動(dòng)set,主要是枯燥且無(wú)技術(shù)含量,不僅耗費(fèi)大量時(shí)間而且很容易出錯(cuò);

所以我們要成為優(yōu)秀的程序員,要多借助輪子,開(kāi)發(fā)效率事半功倍,開(kāi)發(fā)技能也是增長(zhǎng)不少!

如果系統(tǒng)性能沒(méi)有要求,怎么實(shí)現(xiàn)都是好的,但是我們要有追求哈,追求高質(zhì)量!

每個(gè)東西都有存在的價(jià)值,不要捧一踩一哈!

二、MapStruct簡(jiǎn)介

MapStruct是基于JSR 269的Java注釋處理器,用于生成類型安全的 Bean 映射類。

您所要做的就是定義一個(gè)映射器接口,該接口聲明任何所需的映射方法。在編譯過(guò)程中,MapStruct將生成此接口的實(shí)現(xiàn)。此實(shí)現(xiàn)使用純 Java 方法調(diào)用在源對(duì)象和目標(biāo)對(duì)象之間進(jìn)行映射,即無(wú)反射或類似內(nèi)容。

與手動(dòng)編寫映射代碼相比,MapStruct通過(guò)生成繁瑣且容易出錯(cuò)的代碼來(lái)節(jié)省時(shí)間。遵循配置方法的約定,MapStruct使用合理的默認(rèn)值,但在配置或?qū)崿F(xiàn)特殊行為時(shí)會(huì)步入歧途。

圖片

在這里插入圖片描述

三、優(yōu)勢(shì)

與動(dòng)態(tài)映射框架相比,MapStruct具有以下優(yōu)點(diǎn):

  • 通過(guò)使用普通方法調(diào)用而不是反射快速執(zhí)行

  • 編譯時(shí)類型安全:只能映射彼此映射的對(duì)象和屬性,不會(huì)意外地將訂單實(shí)體映射到客戶 DTO 等。

  • 在構(gòu)建時(shí)清除錯(cuò)誤報(bào)告,如果

    • 映射不完整(并非所有目標(biāo)屬性都已映射)
    • 映射不正確(找不到正確的映射方法或類型轉(zhuǎn)換)

性能圖大家可以看一下:

圖片

四、整合實(shí)戰(zhàn)

0. 使用

@Mapper將接口標(biāo)記為映射接口 對(duì)于源對(duì)象和目標(biāo)對(duì)象中具有不同名稱的屬性,可以使用注釋來(lái)配置名稱:@Mapping按照約定,接口聲明一個(gè)成員Mappers INSTANCE,為客戶端提供對(duì)映射器實(shí)現(xiàn)的訪問(wèn)。下面我們來(lái)具體使用!

1. 導(dǎo)入依賴

這里使用最新的,如果引入了lombok可能會(huì)有問(wèn)題,就是他們倆都是在編譯期運(yùn)行的,mapstruct如果比lombok先執(zhí)行,就會(huì)找不到get、set方法,所以會(huì)有問(wèn)題,官網(wǎng)已經(jīng)有了解決方案!現(xiàn)在是啟動(dòng)不會(huì)報(bào)錯(cuò)!

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.3.Final</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

2. 錯(cuò)誤總結(jié)

  • 不會(huì)自動(dòng)生成impl實(shí)現(xiàn)類?

我們需要加上依賴:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.3.Final</version>
</dependency>
  • 重新啟動(dòng)就會(huì)出現(xiàn)和lombok的沖突問(wèn)題:

java: No property named "name" exists in source parameter(s).
 Type "UserVO" has no properties.

官網(wǎng)解決文章地址

<build>
  <pluginManagement>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.1</version>
              <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
                  <annotationProcessorPaths>
                      <path>
                          <groupId>org.mapstruct</groupId>
                          <artifactId>mapstruct-processor</artifactId>
                          <version>1.5.3.Final</version>
                      </path>
                      <path>
                          <groupId>org.projectlombok</groupId>
                          <artifactId>lombok</artifactId>
                          <version>1.18.24</version>
                      </path>
                      <path>
                          <groupId>org.projectlombok</groupId>
                          <artifactId>lombok-mapstruct-binding</artifactId>
                          <version>0.2.0</version>
                      </path>
                  </annotationProcessorPaths>
              </configuration>
          </plugin>
      </plugins>
  </pluginManagement>
</build>

3. 常用實(shí)戰(zhàn)1

用戶表:

@Data
public class User {
    
    private Integer id;
    
    private String username;
    
    private Integer age;
}

前端用戶VO:

@Data
public class UserVO {

    private Integer id;

    private String name;

    private Integer age;
}

我們創(chuàng)建接口進(jìn)行兩個(gè)對(duì)象之間的映射:

import com.example.demo.mapstruct.entity.User;
import com.example.demo.mapstruct.entity.UserVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

/**
 * @author wangzhenjun
 * @date 2023/1/28 16:05
 */
@Mapper
public interface UserMapper {

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

    @Mapping(source ="name",target = "username")
    User userVOToUser(UserVO userVO);

}

屬性多了可以嵌套:

@Mappings({
        @Mapping(source ="name",target = "username"),
        @Mapping(source ="name1",target = "username1")
})

也可以:

@Mapping(source ="name",target = "username")
@Mapping(source ="name1",target = "username1")

編寫測(cè)試類:

@SpringBootTest
class DemoApplicationTests {

    @Test
    void demoMapstruct(){
        UserVO userVO = new UserVO(1,"小紅",18);
        User user = UserMapper.INSTANCE.userVOToUser(userVO);
        System.out.println(user);

    }

}

圖片

我們看到拷貝沒(méi)有任何問(wèn)題!

我們看看是怎么實(shí)現(xiàn)的:

mapstruct會(huì)在編譯期自動(dòng)生成實(shí)現(xiàn)類去幫助我們?nèi)ベx值,不指定默認(rèn)策略,名稱一致進(jìn)行copy!不一致可以按上面的進(jìn)行指定,不指定則不會(huì)有set方法!

圖片

4. 常用實(shí)戰(zhàn)2

下面進(jìn)行多個(gè)源參數(shù)的映射方法演示:

我們把user類加上一個(gè)字段:

private BigDecimal score;

新增加一個(gè)Score類:

@Data
@AllArgsConstructor
public class Score {

    private Integer studentId;

    private BigDecimal score;
}

調(diào)整上面的UserMapper接口:

@Mappings({
       @Mapping(source ="userVO.name",target = "username"),
       @Mapping(source ="score.score",target = "score")
})
User userVOToUser(UserVO userVO, Score score);

測(cè)試代碼:

UserVO userVO = new UserVO(1,"小紅",18);
Score score = new Score(1,new BigDecimal(100));
User user = UserMapper.INSTANCE.userVOToUser(userVO,score);
System.out.println(user);

結(jié)果顯示正常:

圖片

5. 常用實(shí)戰(zhàn)3

我們?cè)賮?lái)看一個(gè)企業(yè)級(jí)能夠用得上的,就是自定義方法,然后進(jìn)行賦值:

場(chǎng)景:一個(gè)商品有長(zhǎng)寬高,我們把長(zhǎng)寬高從cm變?yōu)閙!

還有很多String轉(zhuǎn)Integer、Float等等,都是按照下面這種自定義方法去實(shí)現(xiàn)!

VO和對(duì)象都是一樣的哈!

@Data
@AllArgsConstructor
public class ProductVO {

    private Integer id;

    private String name;

    private BigDecimal length;

    private BigDecimal width;

    private BigDecimal high;

}

看清楚,別導(dǎo)錯(cuò)包了!qualifiedByName:指定自定義方法的名稱@Named("cmToM"):起別名,不使用找不到方法

可以寫一起,也可以整一個(gè)工具類里寫方法,在這里進(jìn)行引用!如果是使用spring,我們可以把接口作為bean進(jìn)行注入調(diào)用(推薦) 加上參數(shù)即可開(kāi)啟:@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)

/**
 * @author wangzhenjun
 * @date 2023/1/28 17:13
 */
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface ProductMapper {

    @Mapping(source = "length",target = "length",qualifiedByName = "cmToM")
    @Mapping(source = "width",target = "width",qualifiedByName = "cmToM")
    @Mapping(source = "high",target = "high",qualifiedByName = "cmToM")
    Product productVOToPrduct(ProductVO productVO);

    @Named("cmToM")
    default BigDecimal cmToM (BigDecimal oldValue){
        if (oldValue == null) {
            return BigDecimal.ZERO;
        }
        return oldValue.divide(new BigDecimal("100"));
    }
}

測(cè)試:

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    private ProductMapper productMapper;

    @Test
    void demoMapstruct(){

        ProductVO productVO = new ProductVO(1,"美麗家園地板",new BigDecimal(100),new BigDecimal(50),new BigDecimal(8));
        Product product = productMapper.productVOToProduct(productVO);

        System.out.println(product);
    }

}

完美轉(zhuǎn)化!

圖片

6. 常用實(shí)戰(zhàn)4

在實(shí)戰(zhàn)一個(gè)LocalDateTime、String相互轉(zhuǎn)化的,后面大家可以去官網(wǎng)文檔去找你需要的:

在剛剛的商品類加個(gè)字段:

private String createdAt;

VO里也加上一個(gè):

private LocalDateTime createdAt;

編寫個(gè)轉(zhuǎn)化類:這里交給spring管理了,因?yàn)镻roductMapper也交給spring管理,不加的話會(huì)找不到此類!

@Component
public class LocalDateTimeMapper {

    public String asString(LocalDateTime date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return date != null ? date.format(formatter): null;
    }

    public LocalDateTime asLocalDateTime(String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return date != null ? LocalDateTime.parse(date,formatter) : null;
    }
}

ProductMapper修改一下:

uses = LocalDateTimeMapper.class使用咱們上面寫的類即可!

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,uses = LocalDateTimeMapper.class)
public interface ProductMapper {

    @Mapping(source = "length",target = "length",qualifiedByName = "cmToM")
    @Mapping(source = "width",target = "width",qualifiedByName = "cmToM")
    @Mapping(source = "high",target = "high",qualifiedByName = "cmToM")
    Product productVOToProduct(ProductVO productVO);

    @Named("cmToM")
    default BigDecimal cmToM (BigDecimal oldValue){
        if (oldValue == null) {
            return BigDecimal.ZERO;
        }
        return oldValue.divide(new BigDecimal("100"));
    }
}

測(cè)試一下:

ProductVO productVO = new ProductVO(1,"美麗家園地板",
new BigDecimal(100),new BigDecimal(50),
new BigDecimal(8), LocalDateTime.now());
Product product = productMapper.productVOToProduct(productVO);
System.out.println(product);

完美轉(zhuǎn)化:

圖片

五、總結(jié)

通過(guò)簡(jiǎn)介到實(shí)戰(zhàn),這時(shí)咱們就是優(yōu)雅的程序員了!

更多的例子可以去官網(wǎng)進(jìn)行查看:

alue.divide(new BigDecimal(“100”));
}
}

測(cè)試一下:

ProductVO productVO = new ProductVO(1,“美麗家園地板”,
new BigDecimal(100),new BigDecimal(50),
new BigDecimal(8), LocalDateTime.now());
Product product = productMapper.productVOToProduct(productVO);
System.out.println(product);

mapstruct開(kāi)發(fā)文檔:https://mapstruct.org/documentation/stable/reference/html/#Preface

到此這篇關(guān)于Java中MapStruct復(fù)制對(duì)象的具體使用的文章就介紹到這了,更多相關(guān)Java MapStruct復(fù)制對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java處理壓縮文件的步驟詳解

    Java處理壓縮文件的步驟詳解

    在Java編程環(huán)境中,處理zip壓縮文件是一項(xiàng)常見(jiàn)的任務(wù),特別是在數(shù)據(jù)傳輸、備份或者打包應(yīng)用程序時(shí),本文將詳細(xì)講解Java處理壓縮文件的步驟,并有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-10-10
  • Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟

    Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟

    這篇文章主要介紹了Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • spring boot實(shí)現(xiàn)profiles動(dòng)態(tài)切換的示例

    spring boot實(shí)現(xiàn)profiles動(dòng)態(tài)切換的示例

    Spring Boot支持在不同的環(huán)境下使用不同的配置文件,該技術(shù)非常有利于持續(xù)集成,在構(gòu)建項(xiàng)目的時(shí)候只需要使用不同的構(gòu)建命令就可以生成不同運(yùn)行環(huán)境下war包,而不需要手動(dòng)切換配置文件。
    2020-10-10
  • 給@Value設(shè)置默認(rèn)值以及為static變量賦值問(wèn)題

    給@Value設(shè)置默認(rèn)值以及為static變量賦值問(wèn)題

    在Spring框架中,@Value注解用于屬性注入,可將配置文件中的值賦給變量,未指定默認(rèn)值時(shí),若配置文件缺少相應(yīng)屬性,程序啟動(dòng)會(huì)報(bào)錯(cuò),可通過(guò)設(shè)定默認(rèn)值防止此問(wèn)題,對(duì)于靜態(tài)變量,由于@Value無(wú)法直接注入,需通過(guò)Set方法賦值,該方法也支持默認(rèn)值設(shè)置
    2024-09-09
  • 詳解springboot讀取yml配置的幾種方式

    詳解springboot讀取yml配置的幾種方式

    這篇文章主要介紹了詳解springboot讀取yml配置的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java中的BlockingQueue接口源碼解析

    Java中的BlockingQueue接口源碼解析

    這篇文章主要介紹了Java中的BlockingQueue接口源碼解析,BlockingQueue接口表示阻塞隊(duì)列,是Java并發(fā)包中阻塞隊(duì)列的接口定義規(guī)范,阻塞隊(duì)列意味著對(duì)于該隊(duì)列的操作是線程安全的,當(dāng)多個(gè)線程存放元素進(jìn)入隊(duì)列或者從隊(duì)列中取出元素都是線程安全的,需要的朋友可以參考下
    2023-11-11
  • SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解

    SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解

    這篇文章主要介紹了SpringBoot利用自定義json序列化器實(shí)現(xiàn)敏感字段數(shù)據(jù)脫敏詳解,因?yàn)榘咐a用到了hutool提供的DesensitizedUtil數(shù)據(jù)脫敏工具類,這里要引入hutool的依賴,如果你需要自定義 數(shù)據(jù)脫敏的邏輯,可以不引入這個(gè)依賴,需要的朋友可以參考下
    2024-01-01
  • Java實(shí)現(xiàn)DFA算法對(duì)敏感詞、廣告詞過(guò)濾功能示例

    Java實(shí)現(xiàn)DFA算法對(duì)敏感詞、廣告詞過(guò)濾功能示例

    本篇文章主要介紹了Java實(shí)現(xiàn)DFA算法對(duì)敏感詞、廣告詞過(guò)濾功能示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • nacos gateway動(dòng)態(tài)路由實(shí)戰(zhàn)

    nacos gateway動(dòng)態(tài)路由實(shí)戰(zhàn)

    這篇文章主要介紹了nacos gateway動(dòng)態(tài)路由實(shí)戰(zhàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java包裝類之自動(dòng)裝箱與拆箱

    Java包裝類之自動(dòng)裝箱與拆箱

    這篇文章主要介紹了Java包裝類之自動(dòng)裝箱與拆箱,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09

最新評(píng)論