Hibernate 和Spring是越來越多的J2EE應用程序使用的兩個突出的開源框架。雖然他們面向的是不同問題,但是他們都有共同的關鍵特征:依賴注射。在返回對象給客戶之前,Spring建立對象之間的依賴關系,這樣減少了在使用這些對象的客戶中的大量代碼。Hibernate專門在返回一個完整的對象模型給客戶之前挑選出數據模型和對象模型之間的依賴關系。當直接使用JDBC來映射數據模型到對象模型的時候,我們通常需要寫大量的代碼來建立對象模型。Hibernate減少了這部分這樣的編碼工作。 Hibernate2.x 提供了基本的表到表的映射,正常的關聯映射(包括一對一,一對多,多對多關系),多態映射,等等。Hibernate3.x通過formula, filter, subselect來增強映射的靈活性,把這些映射提個到另一高度。 在本文中,我們將要向你展現formula的各種特征是如何輔助模式轉換的。在Hibernate3.x之前,formula的屬性僅僅出現在一個property元素中。Hibernate3.x在保持原來用法的同時,還提供了一個formula的屬性或元素(兩者在formula的使用方面都是等價的),能夠用于任何元素中,包括discriminator, many-to-one, one-to-one, element, many-to-many, map-key, map-key-many-to-many, 和 property。這將給對象關系映射(O-R)增加非常大的靈活性,并且可以對復雜的數據模型進行更加精致的解釋。 兩種必須使用formula的主要情景是: 1.需要使用formula計算結果的情形。帶有元素discriminator, element, map-key, map-key-many-to-many, 和 property的formula歸為這一類。 2.需要使用formula來進行連接操作的情形。在元素many-to-one, one-to-one, 和 many-to-many中使用的formula歸為這一類。 第一類:通過公式計算結果 識別器 在實際的數據模式中,常常存在使用一個表來描述另一個表的情況。formula能夠有助于在O-R映射中提供靈活的多態。 在圖1例子中,有兩個表Product和ProductRelease。每一個Product的記錄都在ProductRelease有一個ProductReleaseID的引用,包括產品發布名稱,類型,發行日期等。
在表ProductRelease中有一個讓人感興趣的屬性是SubProductAllowable,它的值要么是0,要么是1。值1就意味著這個產品發布下的任意產品允許有子產品,而值0則意味著不允許這樣的子產品。例如,一些產品是從多個子產品裝配而來的,而另一些產品,他們單獨地成為獨立的單元。 圖2展現了一個解釋這種數據模式的對象模型。Nested的接口定義了getSubProducts和setSubProducts方法。類NestedProduct擴展了基類Product,也實現了接口Nested。產品數據記錄是一個Product還是一個NestedProduct,依賴于產品相應的產品發布記錄的域SubProductAllowable的值。
為了實現這個模型轉換,使用下面的Hibernate3.x的映射: 。糷ibernate-mapping> <class name="Product" discriminator-value="0" lazy="false"> <id name="id" type="long"/> <discriminator formula="(select pr.SubProductAllowable from ProductRelease pr where pr.productReleaseID= productReleaseID)" type="integer" /> <subclass name="NestedProduct" discriminator-value="1"/> </class></hibernate-mapping> 如果formula表達式計算的結果是0,也就是說,該產品不存在子產品,那么,該對象就是類Product的實例。如果結果是1,那么對象就是類NestedProduct的實例。 在表1和2中,對于表Product中的第一個記錄(ProductID=10000001),因為它引用了一個有著SubProductAllowable=1的ProductRelease產品記錄,所以,初始化的類將是NestedProduct。而在產品Product表中的第二個記錄(ProductID=20000001),因為它引用了有著SubProductAllowable=0的表ProductRelease的記錄,所以,初始化類將會是Product。
Property Property元素中的formula允許對象屬性包含某些衍生值,像sum, average, max,等計算的結果, 例如: 。紁roperty name="averagePrice" formula="(select avg(pc.price) from PriceCatalogue pc, SelectedItems si where si.priceRefID=pc.priceID)"/> 而且,formula也有助于從另一表中通過當前記錄的某個屬性值來獲取數據。例如: 。紁roperty name="currencyName" formula="(select cur.name from currency cur where cur.id= currencyID)"/> 這有助于從表currency中檢索currency名稱。正如你看到的那樣,這些直接映射能夠省下許多轉換的代碼。 map-key formula允許map-key擁有任何可能的值。在下面的例子(圖3)中,我們將Role_roleID作為對象模型(圖4)的map-key。
在上面的數據模型中,User和Role通過一個叫做User_has_Role的關系表連接成多對多(many-to-many)關系。為了獲得一個User及其所有與之關聯的Roles,我們可以使用下面的映射: 。糷ibernate-mapping> <class name="User"> <id name="userID"/> <map name="roles" table="UserRole"/> <key column="User_userID"/> <map-key formula="Role_RoleID" type="string"/> <many-to-many column="Role_RoleID" class="Role"/> </map> </class> <class name="Role"> <id name="roleID"/> </class></hibernate-mapping> Role_RoleID被用來作為many-to-many元素的連接域的值。然而,Hibernate并不允許Role_RoleID同時出現在map-key和many-to-many中。但是,使用formula,Role_RoleIDf卻也能夠用于map-key中。 另一種情景:element, map-key-many-to-many, 及其它與property一樣,element能夠被賦給任何有效formula表達式的運算值。 帶有map-key-many-to-many的formula的使用,類似于帶有map-key的formula。然而,map-key-many-to-many常常使用在三重關系中。在三重關系中,一個映射的鍵本身是被參照的對象,而不是一個被參照的屬性。 然而,有幾種formula不支持的情形。一些數據庫(例如Oracle 7)不支持嵌入SQL語句(這就是說,在SQL語句的select部分嵌入SQL語句),在這種情況下,不支持使用formula來計算結果。因此,你需要首先檢查是否支持嵌入SQL語句。 由于來自于Hibernate映射的SQL使用formula表達式作為它的select目標結果的表達式部分,所以,知道一些你所使用的數據庫SQL語句的知識,將有助于你使用formula,盡管這會減少代碼的移植性。 第二種情形:使用formula來連接 多對一 另一個在實際中常見的數據模型是屬性關系映射(proprietary relationship mapping),也就是除了基本的一對一,一對多,多對多關系而外的映射關系。formula是一個用于這種屬性關系管理的元素之一。圖5展現了一個例子,在這個例子中,一個公司可能有許多聯系人,但是他們中僅僅只有一個是缺省的聯系人。有許多聯系人的公司是典型的一對多關系。然而,為了標識缺省聯系人,表ContactPerson使用屬性defaultFlag來標識他們(1表示是,0表示不是)。 圖5.用戶角色數據模式
為了解釋在對象模型中(圖6)缺省聯系人關系,我們使用下面的映射: 。糷ibernate-mapping> <class name="Company" table="Company"> <id name="id" /> <many-to-one name="defaultContactPerson" property-ref="defaultContactPerson"> <column name="id"/> <formula>1</formula> </many-to-one> </class> <class name="Person" > <id name="id" /> <properties name="defaultContactPerson"> <property name="companyID" /> <property name="defaultFlag" /> </properties> </class></hibernate-mapping> 上面,我們將companyID和defaultFlag分組到名為defaultContactPerson的properties元素中,它構成了表Person的唯一鍵值。在Company類中的many-to-one元素與類Person中的defaultContactPerson properties元素相連接。最后的SQL語句如下: select c.id, p.id from Company c, Person p where p.companyID=c.id and p.defaultFlag=1 一對一 在Hibernate中,一對一關系主要用于有著相同主鍵的兩個表連接。我們常常使用多對一關系來表示外部鍵關聯。然而,通過使用formula,一對一關系就能通過外部鍵將表連接。上面的多對一的例子能夠使用如下的一對一的關系映射: 。糷ibernate-mapping> 其他關系:多對多 盡管不常常使用多對多元素的formula,但是,這種formula能夠用于從關系表到一個實體表的特別聯接。結論 本文中的例子展現了大多數formula的使用場景。當需要計算一個formula的值的時候,formula表達式將會出現在最終的SQL語句的select部分。并且當使用一個formula來進行連接的時候,它就出現在最終SQL語句的where部分。而且,只要是目標數據庫支持的任意SQL語句,formula的表達式就能夠使用。其結果是,不需要代碼,formula就能有助于實現從數據模型到對象模型的精確的映射關系。 |
文章來源于領測軟件測試網 http://www.kjueaiud.com/