使用Shark自帶的Hibernate實現代碼替換DODS (2007-10-16 09:32)

在研究工作流引擎shark的時候,在網上找了一點有關Shark的用戶管理模塊爲Hibernate實現的資料:
 
使用Shark自帶的Hibernate實現代碼替換DODS:

    1.使用Hibernate的版本是2.xx,我試了2.00和2.18(2.x最後一個版本),2.00不能用,2.18可以,所以也不計較他們開發的時候具體用那個版本的Hibernate,直接用2.18即可。

    2.將hibernate2.jar和common-lang.jar加入BuildPath,common-lang.jar是Hibernate要用到的。另外要把odmg-3.0.jar、dom4j-1.4.jar、……等包都加入到ClassPath,這些包是反射的方式來調用的,沒有也能編譯,但是運行不了。

    3.無論打算先將哪一個模塊的持久化替換成Hibernate(文中部分使用“Hibernate”指代“Shark源碼中的Hibernate持久層實現”,下同),SharkTransaction和SharkUserTransaction模塊的Hibernate實現是必須要最先做好的。通常SharkUtilities裏面的Hibernate也要使用到,所以優先替換這三個模塊,除了這三個模塊,其他各個模塊的實現基本不耦合。
    這裏要抱怨一下的是,Shark源碼裏面,雖然把整套內核提煉出一個純接口工程,寫在SharkAPI模塊中,同時提供整套實現該接口的實現類,這樣是爲了用戶可以根據自己的需要,可以靈活的重寫一些模塊來完成Shark官方未支持的功能。想法不錯,但是在各個實現類中,很多方法內部都把接到的Interface類型參數轉型成具體Implements Class類型來處理,這樣導致調用者和具體實現者裏面的這個參數必須是同一個實現類產生的,不然就會出現ClassCastException,這樣的直接影響是如果要將DODS換成Hibernate,一換就必須把十幾個模塊的持久層實現全部換掉,不能一部分使用DODS,一部分使用Hibernate,所以要一次完成的改動的代碼量就變得很大,增加調試難度。其實如果一定要做還是可以的,代碼裏面轉型的參數大部分是UserTranaction類型,忽略掉直接提交就是了,當然,這樣會導致事務不統一,玩玩可以,實際系統是不能用的。感覺Shark這部分代碼考慮的不夠完善。

    4.替換Hibernate遇到第一個問題就是無論Shark1.0、1.1還是1.x版中最後的1.1.2中所帶的Hibernate實現都是針對Shark1.0的,或者說,裏面的Hibernate實現在1.0之後就沒人升級維護過。在Shark ReleaseNote裏面寫道一句這樣的話:Contributed Hibernate layers similar to DODS layers for all APIs that have such DODS layers (more than 10 layers). Unfortunatelly, these layers are not worked out completely, and there is nobady to maintain them (especially InstancePersistence layer), and are included only as a source code. 夠faint的-_-#,這十來個要替換的模塊裏面大部分是缺少實現接口中方法,有的是後來接口增加了方法(如它自己提到的“InstancePersistence layer”,就是負責流程實例表、活動實例表、分配表讀寫數據庫最頻繁的一個模塊,有18個方法沒有實現,都是1.0之後加的),有的是實現類實現的接口都不存在了,或者改了另外一個(如SharkTransaction模塊中,Hibernate是實現了SharkTransaction接口,DODS則實現了SharkInternalTransaction接口,後者繼承前者的,增加了幾個方法),所以除非用的是Shark1.0(似乎大部分用的都是1.1.2了)指望更改幾個設置,或者少量代碼就切換過來是不可能的。就算是依葫蘆畫瓢,也得照着DODS的實現,把Hibernate裏面該改的代碼改了,該加的代碼加上纔行。全部要該的地方有兩三千行,全部寫出來不現實,就不寫了。

    5.下一個遇到的困難是Hibernate實現有少許邏輯跟DODS實現不一樣,譬如驗證模塊(Authentication Layer)中,判斷用戶名密碼是否匹配,DODS是將密碼進行SHA-1加密後進行比較的,Hibernate則是直接用密碼明文跟數據庫中的信息進行比較(預留了passwordDigest方法進行加密,該方法直接返回傳入的Password參數),很明顯,兩者不能直接通用。幸好,這樣的地方不多,而且通常一兩句代碼就能修正過來。

    6.替換Hibernate遇到的最大的麻煩是Hibernate與DODS使用數據結構的不一致,這也是Shark1.0和1.1版本歷史差異造成的。最顯而易見不一致就是“oid”:1.1版本中,DODS會用到一個ObjectID表,並將大多數表裏面增加一個oid字段作爲該表的主鍵,而Hibernate實現自然是根據1.0的數據結構,完全不使用到oid的,這樣一來主鍵和外鍵都發生了變化。另外在同一個表裏面的字段的意義也發生了變化,譬如grouptable裏面的groupid字段,DODS認爲是存儲組名稱的,而Hibernate認爲是一個非自然主鍵(既DODS中OID的作用),所以如果之前有使用DODS做了一些數據,中途改爲Hibernate後,就會報“將數據類型 varchar 轉換爲 numeric 時出錯”,更不用說1.1相對1.0所增加的12張表和原有表中增加的一些字段了。要改變Hibernate中的hbm.xml、POJO以及內部訪問代碼的邏輯,才能兼容回1.1的數據結構。
 
 
 

Shark的用戶管理模塊是獨立於其它模塊的,爲了方便與其它系統整合,可以把該模塊改爲Hibernate實現。

Shark中附帶的Hibernate實現代碼是針對Shark 1.0版本的,在當前的版本(1.1-2)中,數據庫的結構和SharkAPI都發生了變化,所以要對Hibernate代碼和數據庫做一些調整。

另外,Shark中附帶的Hibernate實現代碼是Hibernate 2.0的,如果需要,做一些很小的調整就可以升級到Hibernate 3.0

Hibernate代碼的調整完全可以依賴SharkAPI說明來做,由於數據庫主鍵都發生了變化,所有查詢都需要更改。但是由於Shark的查詢方式非常單一,例如對用戶表只有一種查詢方式,對group表也只有一種查詢方式,改動可以很快完成。

Shark用戶模塊的數據庫只有4個表,分別是GroupTableGroupGroupTableUserGroupTableUserTableShark數據庫的主要修改在於主鍵發生了變化。由於DODS的需要,每個表都有OIDVersion兩個列,其中OID是主鍵。因此,主要問題就集中在這兩個字段如何賦值。如果採用的是其它系統的用戶表就沒有這個問題了。

以下三個文件是Hibernate的配置文件:

hibernate.user.cfg.xml

HibernateUser.hbm.xml

HibernateGroup.hbm.xml

放置在{classes}/hbm/UserGroup/目錄下,

org.enhydra.shark.usertransaction.ThreadLocalSession文件中需要指出配置文件的路徑:

   static {

      try {

         sessionFactory = new Configuration().configure(

            "/hbm/UserGroup/hibernate.user.cfg.xml").buildSessionFactory();

      } catch (HibernateException ex) {

         throw new RootError("Exception building SessionFactory: "

                                + ex.getMessage(), ex);

      }

   }

 

shark.conf需要做如下調整:

首先,更換AuthenticationManager接口的實現類,選用HibernateAuthenticationManager

#AuthenticationManagerClassName=org.enhydra.shark.authentication.LDAPAuthenticationManager

#AuthenticationManagerClassName=org.enhydra.shark.authentication.DODSAuthenticationManager

AuthenticationManagerClassName=org.enhydra.shark.authentication.HibernateAuthenticationManager

其次,更換UserGroupManager接口的實現類,選用HibernateUserGroupManager

#UserGroupManagerClassName=org.enhydra.shark.usergroup.LDAPUserGroupManager

#UserGroupManagerClassName=org.enhydra.shark.usergroup.DODSUserGroupManager

UserGroupManagerClassName=org.enhydra.shark.usergroup.HibernateUserGroupManager

第三,更換UserTransactionManager接口的實現類,選擇HibernateUserTransactionFactory

#UserTransactionManagerClassName=org.enhydra.shark.usertransaction.DODSUserTransactionFactory

UserTransactionManagerClassName=org.enhydra.shark.usertransaction.HibernateUserTransactionFactory

總之,用戶管理模塊改爲Hibrnate實現的工作量不大。

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