Java ORM JPA

從事研發管理奔八了,今天有點閒情,記錄一下javaorm經過的日子;


剛工作時,寫過簡單網站,後來做過稍大的Web系統,整過ERP,當然都是Java方向的;


ORM(Object/Relation Mapping)(對象關係映射),相信現在大家已經非常熟悉,並且已經深刻理解;記得剛畢業那會Hibernate就已經非常火爆,當時跟他類似的框架也很多,如企業級的toplink(已經被oracle捐獻給eclipse社區了),大家說半ORM的ibatis等,當時還有apache的commons-dbutils(對JDBC的一個簡單封裝);

toplink:雖然是企業級,代碼質量也有保證,穩定性也有保證,但是因爲沒有hibernate開放,所以當時一般是跟Oracle廠家的產品有關係的開發使用這個最好;

ibatis:它的特點就是純sql語句,網上有專門的測試數據,說它比hibernate執行快,最接近jdbc;後來更名爲mybatis;

(其實不管是什麼數據庫操作框架,查詢數據操作,到最後都是從數據庫中取ResultSet進行讀取)


commons-dbutils:簡單,好用,入門快,看官網幾個eg就行,只需要程序員會sql;


另外一些大型的ERP公司或專業做產品公司,都有公司自己一套ORM,不管是從開源拿來改,還是完全自己開發,都有;


還有Sun又引入了JPA ORM規範,出於兩個原因:其一,簡化現有Java EE和Java SE應用開發工作;其二,Sun希望整合ORM技術,實現天下歸一;

(野心很大!)


使用:

hibernate,我最開始覺得並沒有爲我開發效率提高多少,當時覺得很麻煩,開發網站時用的是dbutils或ibatis,或者直接jdbc,其實這個時候對hibernate的定位錯了,之後做大點的Web系統時,hibernate確實省了不少時間,特別是我們開發了一個hibernate相關自動化生成工具後,效率倍增;當時這個工具是使用dbutils、swing開發出來的,不過後來棄用了,因爲網上出來了更好的工具;


ibatis,剛工作的時候,一個朋友做電信的項目,他們公司技術總監選數據庫框架選的就是ibatis,記得當時他跟我說公司技術總監說這個速度快,當時hibernate效率瓶頸好像爆料不少(現在改變很大,特別是hibernate的緩存技術使效率提高不少);

我用過ibatis和jsf開發過一個系統,感覺查詢很方便,特別是複雜的SQL查詢;沒有做過壓力測試,效率方面不好發表意見;


toplink,這個框架沒使用過,只是得知,是一個企業級的框架,並且有大公司oracle支持;


dbutils,其實這個不算一個ORM框架,但是個人使用的感覺很不錯,寫過不少代碼自動化生成工具,及一些小工具,都是使用的dbutils; 

而且oschina也使用的dbutils;這裏有相關代碼:http://www.oschina.net/code/search?q=dbutils 


我所瞭解的幾個ERP廠商的ORM使用的是自身開發的ORM,因爲一般大型ERP系統都是部署在大型EJB中間件中,遠程調用使用EJB調用,因爲ERP系統最重要的是數據信息和數據安全,像這種企業組件,中間件會賦予很多特性,而且中間件本身也提供很多特性;


jpa,現在jpa已經很成熟穩定了,大家也都用了很長時間,我做的幾個系統也用到了jpa,還不錯,而且事務管理也很方便,移植更改實現也挺方便,因爲有不少變態的客戶,對你做系統的技術,他要參與並且知曉並指定;


不是說jpa沒有缺點,反而缺點很明顯,除了官方缺點,項目開發應用時缺點也很明顯,記得之前一個項目,一個開發人員拿着一個純屬SQL找過來要討論,問JPA裏怎麼查,好像只能返回Entity或List<Object[]>,自定義非Entity對象或其它集合對象均不行;

其實之前項目已經碰到過,不過都是返回List<Object[]>後再進行處理,一般不超過一二十個這樣的查詢,所以之前也就讓開發直接那樣處理,但是現在這個項目報表及複雜數據展現比較多,這種查詢少說也有四五十個以上,考慮增加了一次中間轉換影響效率不少,所以決定修改jpa實現;


分析hibernate jpa實現:

hibernate的EntityManager實現爲:org.hibernate.ejb.AbstractEntityManagerImpl;536行createNativeQuery方法; 由這個入口,進行分析hibernate的jpa實現;

過程略一萬字............

hibernate中處理加載數據集的是org.hibernate.loader.custom.CustomLoader,在其243行有如下代碼:

this.rowProcessor = new ResultRowProcessor(
hasScalars,
       ( ResultColumnProcessor[] ) resultColumnProcessors.toArray( new ResultColumnProcessor[ resultColumnProcessors.size() ] )

這裏就是一個類似ResultSetHandler的實現類,但是是按行處理,所以我們改造時,爲了使改動最小化,也按行處理即可;

其中  Query createNativeQuery(String sqlString, Class resultClass)  中的Class最後存在這個參數中:


麼現在我們看看,它是怎麼傳進這裏的:

如下圖,這是hibernate創建純SQL查詢的方法,最下面的一個方法就是新加的,準備使用ResultSet處理接口:


注意的是,要按第一個紅框中的代碼進行改造,加參數;

如下圖:


然後在Query,NativeSQLQueryPlan,NativeSQLQuerySpecification,SQLQueryImpl,CustomQuery,SQLCustomQuery接口及類中增加RowResultSetProcessor傳遞的方法及屬性;

最後改造一個CustomLoader構造方法最下面的代碼即可,如下:

if (customQuery.getRowResultSetProcessor() == null) {
this.rowProcessor = new ResultRowProcessor(hasScalars,
(ResultColumnProcessor[]) resultColumnProcessors.toArray(new ResultColumnProcessor[resultColumnProcessors
.size()]));
} else {
this.rowProcessor = customQuery.getRowResultSetProcessor();
this.rowProcessor.setHasScalars(hasScalars);
this.rowProcessor.setColumnProcessors((ResultColumnProcessor[]) resultColumnProcessors
.toArray(new ResultColumnProcessor[resultColumnProcessors.size()]));
}

改造完後,編譯覆蓋即可;

當前hibernate版使用的是3.6版;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章