1. 程式人生 > >追求“簡約不簡單”的ORM對映框架

追求“簡約不簡單”的ORM對映框架

  “簡約不簡單”,男人味十足的陳道明的精彩的演繹給我們作了非常好的詮釋。“簡約”也就是要化繁為簡、直接明瞭, 也就是將生活上和設計上多餘的東西撇掉,點到即止。“不簡單”就是隻指“簡約”的背後是一些複雜的設計及功能實現。“簡約不簡單”,是一種相容幷蓄的思想,廣泛來說就是記貼近生活、合乎人性,才是設計的最終目的。

  說起持久層框架或方案,最先想到的肯定是Entity Bean,受過Entity Bean折磨的朋友都知道,其非常的不簡單的同時,也非常的不簡約。不管是CMP還是BMP的Entity Bean,曾經讓J2EE用來作顯耀資本的Entity Bean今天回過頭去看就像一個怪胎,甚至會有一種讓人哭笑不得的感覺。EJB3.0中推出的JPA,終結了“輕量與重量持久之爭”的同時,也宣判了Entity Bean的死刑,基於Entity Bean造價昂貴的系統也成了遺留系統。
  輕量級持久化解決方案設想的萌芽、成形、廣泛應用到最終到打敗Entity Bean的這一過程,給我們揭示了很多現代科學技術發展的客觀規律,我認為其中一個規律可以概括為:“簡約而不簡單”。通過最簡約的表達手段達到最好的表達效果一直是各個不同領域的創造者的目的,軟體也不例外同,因此“簡約主義(英文:minimalism)”應該是我們軟體設計的基本思想之一

  相對於Entity Bean,輕量級持久化方案顯得就“簡約”了許多。不依賴於任何框架的純POJO,即方便領域建模,也方便單元測試,更方便移植、維護及擴充套件。然而,在JDK1.5以前,面對輕量級ORM中的那一堆繁雜的配置檔案,如何有效管理卻是讓人非常頭痛;儘管一些ORM系統通過引入Jakarta Commons Attributes或類似的思想來實現原始碼級標籤宣告持久層物件對映,零亂的標籤定義仍然無法從根本上改善對映屬性配置資訊管理維護的複雜性。

  JDK1.5以後,註解(Annotation)的引入為我們提供了一種非常好的原始碼級配置處理方式。因此,在各種專案中得到了非常好的引用,使得持久層的方案更加簡約。特別是JPA,可算是“簡約”持久層的一個里程碑。因此,現在再來像Spring的Rod Johnson大叔前兩年那樣再來談怎麼滅掉EJB,難免會有點滑稽可笑。

  Hibernate3.2已經實現了JPA,還有很多的持久層ORM框架也將會實現JPA,因此您如果使用這些框架仍然可以在升級版本中享受其一定的簡約。然而“簡約”是無盡頭的,永遠無法輕易達到一種完美的境界,JPA也是如此。

  這裡使用EasyDBO框架,舉一個簡單的例子,來演示“簡約”追求的過程。
  可以不需要使用配置檔案,直接使用Java註解標籤,通過下面的方式定義持久層物件:

@Table(tableName  = " OrderInfo " )
public class  Order  implements  Serializable  {
 @TableField(name 
=
" id " )
 
private  Number id; // 主鍵id

 @TableField(name 
= " sn " )
 
private  String sn; //  定單編號

 @TableField(name 
= " vdate " )
 
private  Date vdate; // 定單日期

 @TableField(name 
= " requireDate " )
 
private  Date requireDate; // 交付日期

 @TableField(name 
= " payType " )
 
private  String payType; // 支付方式

 @TableField(name 
= " linkMan " )
 
private  String linkMan; // 聯絡人

 @TableField(name 
= " tel " )
 
private  String tel; // 電話

 @TableField(name 
= " address " )
 
private  String address; // 地址

 @TableField(name 
= " requirement " )
 
private  String requirement; // 需求描述

 @TableField(name 
= " remark " )
 
private  String remark; // 備註

 @TableField(name 
= " amount " )
 
private  BigDecimal amount; // 訂單總金額

 @TableField(name 
= " handPerson " )
 
private  String handPerson; // 經手人

 @TableField(name 
= " inputUser " )
 
private  String inputUser; // 錄入人

 @TableField(name 
= " inputTime " )
 
private  Date inputTime; // 錄入時間

 @TableField(name 
= " opUser " )
 
private  String opUser; // 操作人

 @TableField(name 
= " opIntro " )
 
private  String opIntro; // 操作簡介

 @TableField(name 
= " opTime " )
 
private  Date opTime; // 操作時間

 @TableField(name 
= " status " )
 
private  Integer status; // 訂單狀態

 @TableField(name 
= " payment " )
 
private  Integer payment; // 支付狀態

 @OneToOne(column 
= " customer_id " , type  =  Customer. class )
 
private  Customer customer; // 一對一關聯,定單對應的客戶

 @ManyToOne(column 
= " order_id " , type  =  OrderDetail. class )
 
private  Set < OrderDetail >  children  = new  HashSet < OrderDetail > (); // 一對多關聯,定單下面的詳細資訊

 
public  Number getId()  {
  
return  id;
 }


 
public void  setId(Number id)  {
  
this .id  =  id;
 }


 
public  String getAddress()  {
  
return  address;
 }

…省略後面普通的getter及setter
}

  由於不再需要使用配置檔案,通過原始碼級的Java註解標籤來標識對映關係,確實要簡單多了,而且也非常方便開發工具識別。然而,如果寫多了,你會發現,那麼多重複的標籤,而且大多數內容又相同或類似,依靠程式碼生成工具總不是辦法。比如@TableField(name=”XXX”),其中,XXX有80%以上都是屬性的欄位的名稱,因此ORM系統應該要提供這些預設配置。下面是刪除掉所有重複、規律一致標籤後的持久層物件Order的改進寫法:

@Table(tableName  = " OrderInfo " )
public class  Order  implements  Serializable  {
 @OneToOne(column 
= " customer_id " , type  =  Customer. class )
 
private  Customer customer; // 一對一關聯,定單對應的客戶
 @ManyToOne(column  = " order_id " , type  =  OrderDetail. class )
 
private  Set < OrderDetail >  children  = new  HashSet < OrderDetail > (); // 一對多關聯,定單下面的詳細資訊

 
private  Number id; // 主鍵id
private  String sn; //  定單編號
private  Date vdate; // 定單日期
private  Date requireDate; // 交付日期
private  String payType; // 支付方式
private  String linkMan; // 聯絡人
private  String tel; // 電話
private  String address; // 地址
private  String requirement; // 需求描述
private  String remark; // 備註
private  BigDecimal amount; // 訂單總金額
private  String handPerson; // 經手人
private  String inputUser; // 錄入人
private  Date inputTime; // 錄入時間
private  String opUser; // 操作人
private  String opIntro; // 操作簡介
private  Date opTime; // 操作時間
private  Integer status; // 訂單狀態
private  Integer payment; // 支付狀態
public  Number getId()  {
  
return  id;
 }

 
public void  setId(Number id)  {
  
this .id  =  id;
 }

…省略後面普通的getter及setter
}



  當然,在上面的POJO中,除了一對一、一對多等關聯需要進行標註以外,其它的都是使用資料表字段名與物件的屬性名相同的對映。追求完美的你還會提出,@OneToOne標籤也應該是可省的,另外,表名、多表對映、關聯欄位等都可以再進一步“簡約”,更多複雜(“不簡單”)的處理,交由ORM框架來處理。

  簡約主義不但是一種文化傾向,是一種時尚潮流,是一種藝術家理想主義的探索,還是一種美學定義或是一種哲學教育,它是一種被建築師、畫家、音樂家、作家在過去幾年中不斷提及的現象,更應該成為我們軟體設計中的一種思想方法及追求的目標。因此,文章結尾忍不住想問一句:今天你“簡約”了嗎?
  
  鑑於國內大量“春迷”的存在,為了照顧廣大“春迷”的情緒,最後補充一段。本文之所以使用EasyDBO作舉例,只是出於對國內開源專案的支援。本人也是EasyDBO的主創人員之一,深知這一框架當前還不完善,還存在著這樣那樣的問題,有很多需要改進的地方。因此,請不要誤認為又在炒作什麼。如果你真正喜歡技術,喜歡開源的話,就請靜下心來,多給我們提一些技術性的建議、不足以及問題,當然更歡迎加入到我們的開發團隊中來,前提是改掉“春迷”所具有的惡習。

 (注:本文作者,EasyJF開源團隊 大峽,版本歸作者所用,轉載請保留版權及作者宣告!謝謝!)