Hibernate <>的一對多和多對一操作真的很方便如果系統采用Hibernate作為持久層完全可以把對應的一對多和多對一邏輯關系放在Hibernate裡面控制減少數據庫的負擔而且也更清晰
多對一和一對多概念
其實這個概念上來說很簡單比如一個客戶可以有多個訂單多個訂單屬於同一個客戶就是最基本的一對多和多對一數據庫使用中感覺多對一和一對多算是比較常見的邏輯關系了
我曾經做過一些數據庫比如某些政府部門的其表單很設計的很簡單粗糙甚至連主鍵都沒有完全靠在事務層補全這些關系其實通過Hibernate持久層來實現邏輯關系也是很不錯的方法下面的例子就是數據庫邏輯上基本沒有定義主要放在持久層裡面這個也主要是我對數據庫操作屬於半通水的原因
數據庫層
這裡面有兩個表單一個CUSTOMER客戶表單一個是ORDERS訂單表單生成客戶表單這個是在SQLServer裡面做的其實其他都一樣因為邏輯關系在Hibernate上面id是主鍵非空其他可以為空
CREATETABLE[dbo][CUSTOMER](
[id][numeric]()NOTNULL
[name][varchar]()NULL
[age][int]NULL
CONSTRAINT[PK_CUSTOMER]PRIMARYKEY)
訂單表單
id為主鍵非空CUSTOMER_id是對應客戶主鍵也非空這裡不做外鍵設置
CREATETABLE[dbo][ORDERS](
[id][numeric]()NULLPRIMARYKEY
[CUSTOMER_id][numeric]()NOTNULL
[ORDER_NUMBER][varchar]()NULL
[PRICE][numeric]()NULL
)
Hibernate設定
HIbernate裡面一對多的對象體現是客戶有一個集合setset裡面放著對應訂單而多對一體現是訂單裡面有一個CUSTOMER對象表明該訂單所屬的客戶其中CUSTOMER類為
publicclassCustomerimplementsjavaioSerializable{
privateLongid;
privateStringname;
privateIntegerage;
privateSetrderses=newHashSet();
}
後面的getXXX和setXXX方法就省去了同樣訂單類就是
publicclassOrdersimplementsjavaioSerializable{
privateLongid;
privateCustomercustomer;
privateStringorderNumber;
privateDoubleprice;
}
而對應hbm文檔就是map文檔如下
CUSTOMERhbmxml
<!DOCTYPEhibernatemappingPUBLIC//Hibernate/HibernateMappingDTD//EN
mappingdtd>
<!
MappingfileautogeneratedbyMyEclipsePersistenceTools
>
<hibernatemapping>
<classnameclassname=onetomanyCustomertable=CUSTOMERschema=dbocatalog=DBTEST>
<idnameidname=idtype=javalangLong>
<columnnamecolumnname=idprecision=scale=/>
<generatorclassgeneratorclass=increment/>
</id>
<propertynamepropertyname=nametype=javalangString>
<columnnamecolumnname=namelength=/>
</property>
<propertynamepropertyname=agetype=javalangInteger>
<columnnamecolumnname=age/>
</property>
<setnamesetname=ordersesinverse=truelazy=truecascade=all>
<key>
<columnnamecolumnname=CUSTOMER_idprecision=scale=notnull=true/>
</key>
<onetomanyclassonetomanyclass=onetomanyOrders/>
</set>
</class>
</hibernatemapping>
這個裡面其他都很簡答了其中<generatorclass=increment/>表示主鍵值自動增加這個主要針對字符串對應的主要體現多對以的是
<setnamesetname=ordersesinverse=truelazy=truecascade=all>
<key>
<columnnamecolumnname=CUSTOMER_idprecision=scale=notnull=true/>
</key>
<onetomanyclassonetomanyclass=onetomanyOrders/>
</set>
其中set表示對應集合fetch和lazy主要是用來級聯查詢的而cascade和inverse主要是用來級聯插入和修改的這幾個主要包括對集合的控制<onetomanyclass=onetomanyOrders/>表示對應類即set裡面包含的類而key主要是用於確定set裡面對應表單列
ORDERS的hbm
<?xmlversionxmlversion=encoding=utf?>
<!DOCTYPEhibernatemappingPUBLIC//Hibernate/HibernateMappingDTD//EN
mappingdtd>
<!
MappingfileautogeneratedbyMyEclipsePersistenceTools
>
<hibernatemapping>
<classcatalogclasscatalog=DBTESTname=onetomanyOrdersschema=dbotable=ORDERS>
<idnameidname=idtype=javalangLong>
<columnnamecolumnname=idprecision=scale=/>
<generatorclassgeneratorclass=increment/>
</id>
<manytooneclassmanytooneclass=onetomanyCustomerfetch=selectname=customer>
<columnnamecolumnname=CUSTOMER_idprecision=scale=/>
</manytoone>
<propertygeneratedpropertygenerated=neverlazy=falsename=orderNumbertype=javalangString>
<columnlengthcolumnlength=name=ORDER_NUMBER/>
</property>
<propertygeneratedpropertygenerated=neverlazy=falsename=pricetype=javalangDouble>
<columnnamecolumnname=PRICEprecision=scale=/>
</property>
</class>
</hibernatemapping>
<manytooneclassmanytooneclass=onetomanyCustomerfetch=selectname=customer>
<columnnamecolumnname=CUSTOMER_idprecision=scale=/>
</manytoone>
表示CUSTOMER熟悉對應的類和其作為key的列名上面這些都可以在MyEclipse裡面自動生成另外注意的一點是在生成的DAO裡面涉及表單操作的save()和delete()方法必須要事件提交數據庫才有反映可以就該Hibernatexml或者用下面這樣代碼來實現
Sessionse=getSession();
Transactiontx=sebeginTransaction();
sedelete(persistentInstance);
//sesave(instance);
mit();
驗證效果
新增用戶
如果新增一個用戶該用戶裡面包含有兩個表單那麼由於持久層已經實現了邏輯關系只要用戶類裡面的set包含了表單則表單可以自動增加實現代碼
CustomerDAOcd=newCustomerDAO();
Customerxd=newCustomer(王小虎null);
Ordersord=newOrders();
ordsetCustomer(xd);
ordsetOrderNumber(王小虎的買單);
Ordersord=newOrders();
ordsetCustomer(xd);
ordsetOrderNumber(王小虎的買單);
Setrderses=newHashSet();
ordersesadd(ord);
ordersesadd(ord);
xdsetOrderses(orderses);
cdsave(xd);
代碼裡面加入一個王小虎用戶兩個訂單通過setOrderses加入只使用cdsave這一個對持久層操作完成後查詢
王小虎
=================================
王小虎的買單
王小虎的買單
顯示CUSTOMER裡面加入了王小虎ORDERS裡面也加入他的訂單
刪除操作
List<Customer>csList=cdfindByProperty(name王小虎);
for(Customercs:csList){
cddelete(cs);
}
這個很簡單了通過其中findByProperty(name王小虎);對應SQL為deletefromtableCUSTOMERwherename=王小虎;刪除了王小虎而ORDERS裡面王小虎對應的表單也同時被刪除
小小總結
Hibernate的多對一和一對多處理還是挺方便的如果在減少數據庫復雜度的原則來說把一些邏輯處理放在持久層是一個常見的方法
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28543.html