# 牛年自強計畫 Week 7 - SpringBoot - POJO 介紹 ## 【前言】 Java 開發人員應該常會接觸到所謂的 PO、VO、BO、DTO、DAO 等等物件名稱。 他是一個實際的類或套件嗎? 還是理念的實現? 還是約定俗成的類群名稱? 是 JavaBean? 是 Entity? 如果你有不了解、不清楚、覺得有誤區的話,那接下來的內容將幫助你理解何謂 POJO,以及它們在 Java 中的角色。 ## 【POJO】  全名 **Plain Old Java Object**,意為 **簡單 Java 物件** (絕對不是什麼老 Java 物件...),是 **Martin Fowler**、**Rebecca Parsons** 和**Josh MacKenzie** 在 2000 年時提出。 因為 POJO 並沒有嚴謹規範的定義,因此 Kai 整理了 POJO 的 **核心精神** 列在下方,幫助大家更容易理解: - **簡單、普通的 Java 物件** - **可包含業務處理邏輯或資料持久化邏輯** - **不可繼承或實現他類 (不包含實現序列化)** - **不受限制的類,包含上述為不可繼承、不可實現、不可作 Annotation 處理 (然而現在越來越多 @Annotation 風格的 POJO 導致這部分已不符合技術潮流而拿掉)** 很多人會把 **POJO** 跟 **JavaBean** 搞混,來看看 **JavaBean** 的 **約定**: - **須有一個 public 的無參數建構子** - **所有屬性設置為 private** - **屬性需透過 setter/getter 處理,並有命名的規範** - **可序列化** - 能夠靈活被應用到其他類當中 可以發現 JavaBean 的約定比起 POJO 來說,在針對屬性與其方法的部分更嚴謹,因此可以把 JavaBean 視為 **遵從特定屬性處理與命名規範的POJO** **※ 兩者最大差別為 JavaBean 不會有業務邏輯處理部分,但 POJO 可以** 而一般我們熟知的 **Entity** 則是: - **設有配對 DB Table 的環境參數屬性或 Annotaion** - **設有配對 DB Table 的 Key 屬性或 Annotation** - **設有配對 Columns 的屬性與對應的 setter/getter 方法** - **可序列化** 在這之中頻繁使用到 Annotation 的部份則已將 **Entity** 與 **POJO** 給視為兩種不同的東西。 兩者在資料處理方面有沒有相似? 非常相似,甚至可以說很多人都搞不懂兩者區別。 簡單來說,**Entity 是面向 DB 的物件**,處理的不僅有資料持久化,還包含配對 Table 的設定,而 **POJO 則面向程式**,更靠近 **JavaBean** 的定位。兩者在實務上是可以搭配使用的,並不侷限說只能採用一種。 > 理論要套用到實務面往往會遇到很多困難,Entity 和 POJO 要如何搭配使用除了要懂其理論與核心精神以外,更講究經驗法則,架構師的影響格外重大。畢竟在現實層面來說,實作比理論還重要,但理論可以讓實作更明確和清晰。 ## 【分類】 POJO 可以視為一個中間對象,正如上述所言,POJO 與 JavaBean 的定位非常類似,但自由度上又比 JavaBean 高,例如: 我們常看到的 DAO 類就是一種 POJO POJO 在不同狀況下又分為下列幾種: | 名稱 | 全名 | 適用狀況 | | ---- | ---- | ---- | | **PO** | **Persistant Object** | 與資料來源直接相關的類 | | **DTO** | **Data Transfer Object** | 與資料傳輸相關的類 | | **VO** | **Value Object** | 資料與使用者直接相關的類 | | **DAO** | **Data Access Object** | 封裝與 DB 連動,並轉換資料為 PO 的類 | | **BO** | **Buesiness Object** | 負責集合 PO/VO 相關的類 | ### 【PO】 在 Entity 概念出來之前,作為與 DB Table 映射對照用的 POJO 類,其組成為對照 Columns 的屬性以及 setter/getter 方法,亦可稱其為一個純粹的 JavaBean。一個實體負責對應一筆資料。 作為一個 PO,除了上述以外,還須符合以下幾個條件: - 不可包含任何對資料庫的操作 - 屬性與 Columns 名稱一一對應 - 必須序列化 在 ORM 中存在的 PO 亦可視作一個完全純粹的 JavaBean #### 【PO】範例 ```java= public class table{ private String column1; private int column2; public void setColumn1(String column1){ this.column1 = column1; } public void setColumn2(int column2){ this.column2 = column2; } public String getColumn1(){ return this.column1; } public int getColumn2(){ return this.column2; } } ``` ### 【DTO】 當資料的處理階段已從源頭取得、並且進行了調整後,進入傳輸的階段,這一個階段的資料類別會被稱為 DTO。 簡單來說,無論是從 DB 取出完整的100個欄位的資料列,或是 remote 得到的資料集合多大。 若下一個步驟是需要經過一段處理(縮減到50個欄位、增加到150個欄位、或整合資料集合之類)再轉傳出去的話,這些負責轉傳處理後資料持久化的類別就稱做 DTO。 ### 【VO】 與 DTO 的前半部分相同,但後半部分為當資料的接收者為終端用戶(客戶、使用者等),這些類別稱為 VO。 通常也作為業務邏輯層的資料持久化類別,負責提供給 API 作為提供回應類別用。 > VO 與 DTO 最大的區別在於: > - VO 通常是作為傳與前端展示給客戶、使用者查看的資料類別 > - DTO 則是後端負責跟諸多服務溝通用的資料類別 > > 而兩者的資料來源都可能為 PO 或其他服務提供 ### 【DAO】 DAO 是一開始接觸 DB 處理資料時候最常用到的類別,主要用來 1. 封裝訪問 DB 的方法並提供給業務邏輯層的類別使用 2. 將取得的資料轉換為 PO 類別做持久化處理 ### 【BO】 BO 是比較特別的 POJO 類,他的概念偏向 POJO 的集合,是作為一個含括其它 PO 或 VO 使用的類別存在。 例如:一個運動員,我們可以把他的球類運動成績寫成一個 PO、田徑運動成績寫成第二個 PO、其它類推,這些 POs 總括起來可以是該名運動員的 BO,往後我們需要查閱該運動員的項目資料,只需要從這個 BO 中取出對應的 PO 即可。 ## 【心得】 POJO類看半天會朦是真的,實際難完全應用於工作上,畢竟不是每一位工程師都理解清楚各個 POJO 類的意義與使用情境,所以建議使用以少量幾種即可,例如 VO DTO 這種常用的。 PO 和 DAO 因為目前 SpringBoot + ORM Entity 的模組,已經自動封裝處理的關係,應該不會需要自行寫到。 工程類的東西,講求精益求精的同時,也要看看這份精是否可以傳承下去? 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Spring Boot`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up