DO、DTO、BO、AO、VO、POJO定義和轉換的正確姿勢(轉)


一、引言

DO、DTO、BO、AO、VO、POJO的概念看似簡單,但是想區分好或者理解好也不容易,本文簡單梳理一下。通過各層POJO的使用,有助於提高代碼的可讀性和可維護性。

二、區別

《阿里巴巴Java開發規范》關於領域模型的部分介紹如下:

分層領域模型規約:
    DO(Data Object):此對象與數據庫表結構一一對應,通過 DAO 層向上傳輸數據源對象。
    DTO(Data Transfer Object):數據傳輸對象,Service 或 Manager 向外傳輸的對象。
    BO(Business Object):業務對象,由 Service 層輸出的封裝業務邏輯的對象。
    AO(ApplicationObject):應用對象,在Web層與Service層之間抽象的復用對象模型, 極為貼近展示層,復用度不高。
    VO(View Object):顯示層對象,通常是 Web 向模板渲染引擎層傳輸的對象。
    Query:數據查詢對象,各層接收上層的查詢請求。注意超過 2 個參數的查詢封裝,禁止
    使用 Map 類來傳輸。


最難理解的是BO,大致這么理解:
BO這個對象可以包括一個或多個其它的對象。
比如一個簡歷,有教育經歷、工作經歷、社會關系等等。
我們可以把教育經歷對應一個PO,工作經歷對應一個PO,社會關系對應一個PO。
建立一個對應簡歷的BO對象處理簡歷,每個BO包含這些PO。這樣處理業務邏輯時,我們就可以針對BO去處理。

------------------------------------------------------------------------------------------------------------------------------------------------------

大致的示例代碼:
1) Controller層
public List<UserVO> getUsers(UserQuery userQuery);
此層常見的轉換為:DTO轉VO

2) Service層、Manager層
// 普通的service層接口
List<UserDTO> getUsers(UserQuery userQuery);
然后在Service內部使用UserBO封裝中間所需的邏輯對象

// 來自前端的請求
List<UserDTO> getUsers(UserAO userAo);
此層常見的轉換為:DO轉BO、BO轉DTO

3) DAO層
List<UserDO> getUsers(UserQuery userQuery);


三、各種對象該怎么轉換?

那么這里又涉及到另外一個問題,各種對象轉換該怎么辦呢?常見的寫一個轉換方法,然后手動調用get/set方法,屬性太多非常痛苦,容易遺漏或者重復,而且效率非常低下。
推薦兩種方式:
  1)通過IDEA插件實現快速自動生成轉換代碼。如Generate All setters插件,參見 超實用的IDEA插件推薦,定義好參數和返回值,使用快捷方式可以輕松生成轉換的代碼。
  2)通過第三方轉換庫來轉換。
  - Apache org.apache.commons.beanutils.PropertyUtils.copyProperties
  - Apache org.apache.commons.beanutils.BeanUtils.copyProperties
  - Spring org.springframework.beans.BeanUtils.copyProperties
  - Cglib BeanCopier
  - Dozer
  - orika

對應的maven依賴(已經給出了maven地址,建議用最新版本)

<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.11</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/net.sf.dozer/dozer -->
<dependency>
    <groupId>net.sf.dozer</groupId>
    <artifactId>dozer</artifactId>
    <version>5.5.1</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/ma.glasnost.orika/orika-core -->
<dependency>
    <groupId>ma.glasnost.orika</groupId>
    <artifactId>orika-core</artifactId>
    <version>1.5.4</version>
</dependency>


從效率來講,讀過其他文章,綜合而言cglib應該最高,其次是orika。因為cglib用的是asm,直接操作內存對象的字節碼增強技術。orika用的是javassist,通過動態字節碼生成實現對象轉換。

具體用法在這里就不介紹了,需要的話去官網看看文檔也可以去github看下demo。

我的看法:
第二種代碼實現對象轉換簡潔並且功能強大,但是我個人非常推崇第一種寫轉換方法的方式,因為這種方式對象屬性改變可以直觀反映到代碼上,也可以避免因為粗心和增刪屬性等出現的莫名其妙的錯誤。
————————————————
版權聲明:本文為CSDN博主「明明如月學長」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/w605283073/article/details/89715188


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM