成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

高效、優(yōu)雅的對(duì)象Copy之MapStruct入門(mén)到精通,實(shí)戰(zhàn)踩坑版

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

一、前言

大家在開(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注釋處理器,用于生成類(lèi)型安全的 Bean 映射類(lèi)。

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

與手動(dòng)編寫(xiě)映射代碼相比,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í)類(lèi)型安全:只能映射彼此映射的對(duì)象和屬性,不會(huì)意外地將訂單實(shí)體映射到客戶(hù) DTO 等。
  • 在構(gòu)建時(shí)清除錯(cuò)誤報(bào)告,如果
  • 映射不完整(并非所有目標(biāo)屬性都已映射)
  • 映射不正確(找不到正確的映射方法或類(lèi)型轉(zhuǎn)換)

性能圖大家可以看一下:

圖片

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

1、使用

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

2、. 導(dǎo)入依賴(lài)

這里使用最新的,如果引入了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>

3、錯(cuò)誤總結(jié)

  1. 不會(huì)自動(dòng)生成impl實(shí)現(xiàn)類(lèi)?

我們需要加上依賴(lài):

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.3.Final</version>
</dependency>
  1. 重新啟動(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)解決文章地址:https://mapstruct.org/faq/#Can-I-use-MapStruct-together-with-Project-Lombok。

<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>

4、常用實(shí)戰(zhàn)一

用戶(hù)表:

@Data
public class User {

private Integer id;

private String username;

private Integer age;
}

前端用戶(hù)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")

編寫(xiě)測(cè)試類(lèi):

@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)類(lèi)去幫助我們?nèi)ベx值,不指定默認(rèn)策略,名稱(chēng)一致進(jìn)行copy!不一致可以按上面的進(jìn)行指定,不指定則不會(huì)有set方法!

圖片

5、常用實(shí)戰(zhàn)二

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

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

private BigDecimal score;

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

@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é)果顯示正常:

圖片

6、常用實(shí)戰(zhàn)三

我們?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:指定自定義方法的名稱(chēng)。

@Named("cmToM"):起別名,不使用找不到方法。

可以寫(xiě)一起,也可以整一個(gè)工具類(lèi)里寫(xiě)方法,在這里進(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)化!

圖片

7、常用實(shí)戰(zhàn)四

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

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

private String createdAt;

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

private LocalDateTime createdAt;

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

@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使用咱們上面寫(xiě)的類(lèi)即可!

@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)化:

圖片

責(zé)任編輯:姜華 來(lái)源: 小王博客基地
相關(guān)推薦

2022-09-02 15:11:18

開(kāi)發(fā)工具

2012-02-29 00:49:06

Linux學(xué)習(xí)

2011-06-07 10:33:11

Android Activity

2023-11-08 08:32:16

2010-02-06 15:31:18

ibmdwAndroid

2009-07-22 14:55:16

ibmdwAndroid

2016-12-08 22:39:40

Android

2017-05-09 08:48:44

機(jī)器學(xué)習(xí)

2025-04-22 07:52:59

2025-02-24 10:07:10

2022-06-10 08:17:52

HashMap鏈表紅黑樹(shù)

2025-05-12 10:15:00

Linuxdiff系統(tǒng)

2023-02-20 08:11:04

2024-02-26 08:52:20

Python傳遞函數(shù)參數(shù)參數(shù)傳遞類(lèi)型

2010-11-08 10:20:18

2010-02-07 10:25:11

Android

2020-06-04 12:15:37

Go內(nèi)存池對(duì)象池

2024-04-10 08:39:56

BigDecimal浮點(diǎn)數(shù)二進(jìn)制

2023-01-18 23:20:25

編程開(kāi)發(fā)

2020-09-15 08:46:26

Kubernetes探針服務(wù)端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日本精品免费 | 久久亚洲国产精品日日av夜夜 | 亚洲精品视频二区 | 日韩一区欧美一区 | 一区二区三区欧美在线 | 亚洲欧美精品国产一级在线 | 亚洲欧美精品国产一级在线 | 成人av片在线观看 | 欧美精品区| 玖玖精品视频 | 午夜精品久久久久久久久久久久久 | 妞干网福利视频 | 日日天天 | 99热这里有精品 | 玖玖综合网 | 日韩欧美中文字幕在线观看 | 国产精品中文字幕在线观看 | 免费成人高清 | 中文精品视频 | 精品福利在线 | 国产日韩久久久久69影院 | 伊人伊人伊人 | 久久久女女女女999久久 | 99re在线免费视频 | 国产99在线 | 欧美 | 九九热这里只有精品在线观看 | 99福利视频 | 精品1区2区 | 日韩精品一区二区三区视频播放 | 日韩美女一区二区三区在线观看 | 在线视频一区二区 | 国产精品福利久久久 | 亚洲国产视频一区二区 | 国产一区视频在线 | 午夜久久久 | 欧美三级三级三级爽爽爽 | 欧美一区二区三区在线观看视频 | 中文字幕在线剧情 | 亚洲精品久久久久久一区二区 | 一区二区三区在线观看视频 | 成人精品一区二区三区 |