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

實(shí)體到 DTO 轉(zhuǎn)換!這七種方式性能差距太大,最后一個(gè)才是王者

開發(fā) 前端
實(shí)體到DTO的轉(zhuǎn)換過程旨在將復(fù)雜的實(shí)體對象轉(zhuǎn)換為更簡潔、更適合傳輸?shù)腄TO對象,從而隱藏業(yè)務(wù)邏輯細(xì)節(jié),提高數(shù)據(jù)傳輸效率和安全性。

環(huán)境:SpringBoot3.2.5

1. 簡介

在項(xiàng)目開發(fā)中,實(shí)體(Entity)到DTO(Data Transfer Object,數(shù)據(jù)傳輸對象)的轉(zhuǎn)換是一個(gè)常見的需求,特別是在前后端分離或微服務(wù)架構(gòu)中。實(shí)體通常代表數(shù)據(jù)庫中的表結(jié)構(gòu),包含業(yè)務(wù)數(shù)據(jù)和狀態(tài),而DTO則是一種用于封裝和傳輸數(shù)據(jù)的輕量級對象,主要用于在不同層或服務(wù)之間傳遞數(shù)據(jù)。

實(shí)體到DTO的轉(zhuǎn)換過程旨在將復(fù)雜的實(shí)體對象轉(zhuǎn)換為更簡潔、更適合傳輸?shù)腄TO對象,從而隱藏業(yè)務(wù)邏輯細(xì)節(jié),提高數(shù)據(jù)傳輸效率和安全性。

有效的實(shí)體到DTO轉(zhuǎn)換策略能夠減少數(shù)據(jù)傳輸量,提升系統(tǒng)性能,并增強(qiáng)系統(tǒng)的可維護(hù)性和可擴(kuò)展性。

  • Spring BeanUtils
  • Apache BeanUtils
  • Orika
  • Cglib BeanCopier
  • ModelMapper
  • MapStruct
  • Getter/Setter

以上對象的轉(zhuǎn)換,你用過哪幾種?

1.1 環(huán)境準(zhǔn)備

接下來,我們先準(zhǔn)備2個(gè)類,Entity與DTO類

// Entity類
public class User {
  private Long id;
  private String code;
  private String email;
  private String name;
  private String qq;
  private String table;
  private String address;
  // getter / setter
}
// DTO類
public class UserDTO {
  private Long id;
  private String code;
  private String email;
  private String name;
  private String qq;
  private String table;
  private String address;
  // getter / setter
}

實(shí)體類與DTO類完全一樣。

我們下面的測試都會基于下面的數(shù)據(jù)進(jìn)行測試:

User user = new User() ;
user.setId(1L) ;
user.setCode("S0001") ;
user.setEmail("pack@qq.com") ;
user.setName("N") ;
user.setQq("6666666") ;
user.setTable("CTO") ;
user.setAddress("XJ") ;

接下來,我們將詳細(xì)的介紹每一種轉(zhuǎn)換工具的基本使用及其性能情況。

2. 性能對比

2.1 Spring BeanUtils

該工具類是Spring提供位于spring-beans.jar包中。如下是基本使用:

UserDTO target = new UserDTO() ;
BeanUtils.copyProperties(target, user) ;

接下來我們進(jìn)行10000次的循環(huán)測試

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  UserDTO target = new UserDTO() ;
  org.springframework.beans.BeanUtils.copyProperties(target1, user) ;
}
System.out.println("Spring BeanUtils: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

Spring BeanUtils: 55ms

平均在55ms完成。

注意:首次進(jìn)行copyProperties時(shí)會慢,因?yàn)樗鼉?nèi)部會通過內(nèi)省獲取屬性信息然后緩存,之后直接從緩存中獲取,后續(xù)速度會非常快。

2.2 Apache BeanUtils

我們需要引入以下包

<dependency>
  <groupId>commons-beanutils</groupId>
  <artifactId>commons-beanutils</artifactId>
  <version>1.9.4</version>
</dependency>

基本使用示例:

UserDTO target = new UserDTO() ;
BeanUtils.copyProperties(target, user) ;

與Spring的基本一樣。進(jìn)行10000次的循環(huán)測試

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  UserDTO target = new UserDTO() ;
  BeanUtils.copyProperties(target, user) ;
}
System.out.println("Apache BeanUtils: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

Apache BeanUtils: 113ms

該BeanUtils內(nèi)部也是通過內(nèi)省+Cache的方式進(jìn)行處理,但是它的效率相比Spring BeanUtils慢了至少1倍。

2.3 Orika

Orika 能夠遞歸地(以及其他功能)將一個(gè)對象的數(shù)據(jù)復(fù)制到另一個(gè)對象中。在開發(fā)多層應(yīng)用程序時(shí),它非常有用。

引入以下依賴

<dependency>
  <groupId>ma.glasnost.orika</groupId>
  <artifactId>orika-core</artifactId>
  <version>1.5.4</version>
</dependency>

基本使用示例:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder()
  .build() ;
MapperFacade mapper = mapperFactory.getMapperFacade();
UserDTO dto = mapper.map(user, UserDTO.class) ;

如果需要我們還可以注冊類型字段的映射關(guān)系,如下:

mapperFactory.classMap(User.class, UserDTO.class)
  .field("id", "id")
  .field("code", "code")
  .field("email", "email")
  .field("name", "name")
  .field("qq", "qq")
  .field("table", "table")
  .field("address", "address")
  .byDefault()
  .register() ;

類之間的字段如何進(jìn)行映射。

接下來,進(jìn)行10000次的循環(huán)測試

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  mapper.map(user, UserDTO.class) ;
}
System.out.println("orika: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

orika: 24ms

目前來看性能相當(dāng)不錯(cuò)。

2.4 Cglib BeanCopier

因?yàn)槲耶?dāng)前是基于Spring Boot環(huán)境,而該BeanCopier類位于spring-core.jar包中。

基本使用示例:

UserDTO target = new UserDTO() ;
BeanCopier.create(User.class, UserDTO.class, false)
  .copy(user, target, null) ;

與上面的BeanUtils差不多一行代碼搞定。進(jìn)行10000次的循環(huán)測試

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  UserDTO target = new UserDTO() ;
  BeanCopier.create(User.class, UserDTO.class, false)
    .copy(user, target, null) ;
}
System.out.println("Cglib BeanCopier: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

Cglib BeanCopier: 17ms

性能更高了。

2.5 ModelMapper

該開源組件,在之前的文章中已經(jīng)介紹過了,我們這里就不在啰嗦了,我們直接進(jìn)行10000次測試。

ModelMapper mapper = new ModelMapper() ;
long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  mapper.map(user, UserDTO.class) ;
}
System.out.println("modelmapper: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

modelmapper: 145ms

似乎不是很理想啊。

2.6 MapStruct

MapStruct 是一個(gè)代碼生成器,它基于約定優(yōu)于配置的方法,極大地簡化了 Java Bean 類型之間映射的實(shí)現(xiàn)。生成的映射代碼使用普通的方法調(diào)用,因此速度快、類型安全且易于理解。

MapStruct在編譯時(shí)生成bean映射,這確保了高性能。它是一個(gè)注解處理器,它被插入到 Java 編譯器中,既可以在命令行構(gòu)建(如 Maven、Gradle 等)中使用。

首先,引入依賴。

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

我們還需要配置編譯插件。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>${java.version}</source>
    <target>${java.version}</target>
    <annotationProcessorPaths>
      <path>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.6.3</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

基本使用示例:

定義映射接口

@Mapper
public interface UserMapper {
  UserMapper INSTANCE = Mappers.getMapper(UserMapper.class) ;
  
  UserDTO userToUserDTO(User user) ;
}

使用

UserMapper.INSTANCE.userToUserDTO(user) ;

上面的插件會根據(jù)這里的映射接口Mapper,自動生成接口實(shí)現(xiàn)類

圖片圖片

而我們不需要直接去使用該實(shí)現(xiàn)類,這是由mapstruct來調(diào)用。

進(jìn)行10000的測試。

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  UserMapper.INSTANCE.userToUserDTO(user) ;
}
System.out.println("mapstruct: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

mapstruct: 25ms

看起來也還是非常優(yōu)秀的。

2.7 Getter/Setter

此種方式就是我們自己在代碼中進(jìn)行g(shù)etter/setter操作。所以,這里我們直接進(jìn)行10000次的測試

long start = System.currentTimeMillis() ;
for (int i = 0; i < 10000; i++) {
  UserDTO target = new UserDTO() ;
  target.setId(user.getId()) ;
  target.setAddress(user.getAddress()) ;
  target.setCode(user.getCode()) ;
  target.setEmail(user.getEmail()) ;
  target.setName(user.getName()) ;
  target.setQq(user.getQq()) ;
  target.setTable(user.getTable()) ;
}
System.out.println("Getter Setter: " + (System.currentTimeMillis() - start) + "ms") ;

輸出結(jié)果

Getter Setter: 2ms

雖然要寫更多的代碼了,但是性能確是最高的。

2.8 最后總結(jié)

圖片圖片

要論工具的強(qiáng)大,MapStruct 和 ModelMapper 無疑是佼佼者,但相對而言,MapStruct 的配置和使用略顯復(fù)雜,ModelMapper相對簡單多了,不需要額外的插件支持。如果你對性能的要求不是極高,選擇 MapStruct 依然是一個(gè)明智且不錯(cuò)的選擇。然而,如果你追求極致的性能優(yōu)化,那么手動編寫 getter/setter 代碼可能會是更優(yōu)的方案。

責(zé)任編輯:武曉燕 來源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2025-01-21 08:00:00

限流微服務(wù)算法

2018-06-10 16:31:12

2017-06-14 16:44:15

JavaScript原型模式對象

2025-02-10 08:43:31

Java異步編程

2022-07-01 08:00:44

異步編程FutureTask

2018-03-13 09:00:01

IT架構(gòu)

2023-09-26 08:20:12

消息隊(duì)列RabbitMQ

2018-03-22 04:48:06

2022-03-18 14:33:22

限流算法微服務(wù)

2022-12-23 10:55:09

CIO方式團(tuán)隊(duì)

2024-12-20 12:10:19

2020-12-01 00:15:04

勒索軟件漏洞網(wǎng)絡(luò)攻擊

2010-10-15 10:02:01

Mysql表類型

2025-05-13 08:20:58

2021-07-23 17:15:12

物聯(lián)網(wǎng)IOT

2020-01-16 12:20:03

人工智能AI稅收

2023-07-06 10:36:51

人工智能

2023-09-11 14:26:44

智能技術(shù)人工智能

2023-09-07 10:39:25

AI供應(yīng)鏈

2023-01-03 13:43:55

團(tuán)隊(duì)首席信息官
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 一本一道久久a久久精品综合蜜臀 | 久久国产一区二区三区 | 日韩一区和二区 | 日本福利在线观看 | 黄免费观看视频 | 一区二区播放 | 日韩在线精品视频 | 羞羞视频免费观看入口 | 中文字幕97 | 亚洲国产精品99久久久久久久久 | 欧美日韩国产精品激情在线播放 | 久久久久久久久久久久久9999 | av在线播放网站 | 国产精品99久久久久久www | 精品二区视频 | 亚洲一区二区在线播放 | 久久男人| 一区二区三区久久 | 日本久久黄色 | 国产精品亚洲成在人线 | 日韩在线视频观看 | 一区二区三区视频在线免费观看 | 日韩日韩日韩日韩日韩日韩日韩 | 最新中文字幕在线 | 国产精品一区二区av | 精品久久久久久久久久久久久久 | 精品国产不卡一区二区三区 | 国产精品视频入口 | 国产精品3区| 日本成人在线观看网站 | 毛片网站免费观看 | 尤物视频在线免费观看 | 欧美一区2区三区4区公司二百 | 中文字幕在线免费观看 | 久久国产秒 | 色本道| 在线看国产 | 久久成人国产 | 亚洲码欧美码一区二区三区 | 最新国产在线 | 欧美亚洲国语精品一区二区 |