Posted on 2007-10-12 10:46
semovy 閱讀(303)
評論(0) 編輯 收藏 所屬分類:
EJB
實體之間的級聯(lián)關系
我們在以前的七種關系映射中經(jīng)常會在注釋中看到如下方法:cascade(),它表示級聯(lián),也就是有關聯(lián)的一些實體,當我們對其中的一些進行操作的時候,與它相關聯(lián)的實體應該怎么辦。這樣時候,就需要我們定義cascade的屬性了,cascade一共有五種屬性,我們可以用其中的一種,也可以用其中的多種混合,其中可用的屬性如下:
public enum CascadeType
{
ALL, PERSIST,
MERGE, REMOVE,
REFRESH
}
屬性中ALL表示所有的級聯(lián),如果選了它就表示所有的級聯(lián)了,也就不必選其它的了。下面我們一個一個來講講它們的用處吧:
1,PERSIST
PERSIST的意思就是持久的意思,它表示當我們對其中一個實體進行持久化操作的時候,與它相關聯(lián)的也同樣持久化進數(shù)據(jù)庫,也就是執(zhí)行insert動作。這樣在我們保存的時候,只需要保存一個實體就可以了,與它相關聯(lián)的實體也會被同時保存。
Customer cust = new Customer( );
Address address = new Address( );
cust.setAddress(address);
entityManager.persist(cust);
在上面的代碼中,我們只需要持久化cust就可以了,與cust相關聯(lián)的Address會自動被保存進數(shù)據(jù)庫。如果我們沒有指定PERSIST關聯(lián),那么我們就需要再調(diào)用entityManager.persist(address)來保存Address,這樣就比較麻煩了。
2,MERGE
MERGE就是合并的意思,也就是把當前的實體BEAN的內(nèi)容合并到數(shù)據(jù)庫里面去,如果當前實體BEAN在數(shù)據(jù)庫里面沒有相應的記錄,則它會自動插入新的記錄,在這一點上,它和PERSIST比較相似。
cust.setName("William");
cust.getAddress( ).setCity("Boston");
entityManager.merge(cust);
在以上代碼中,當我們把cust的名字改了,并且把地址里面的城市名也改了以后,我們合并到數(shù)據(jù)庫的時候,Address表中的數(shù)據(jù)也一樣會跟著更新,那如果我們新加一個地址進去呢?會怎么樣呢?結果還是一樣的,如果EntityManager發(fā)現(xiàn)沒有這條數(shù)據(jù)時,它為了把主體合并到數(shù)據(jù)庫里面去,它就會插入一個新的實體到數(shù)據(jù)庫中。在我們在一對多的時候,可以看到這一點:
Phone phone = new Phone( );
phone.setNumber("617-666-6666");
cust.getPhoneNumbers( ).add(phone);
Customer newCust=entityManager.merge(cust);
在這里加了一個新的號碼,然后我們合并cust,結果新的phone也被插入數(shù)據(jù)庫了。在這里我們要注意的一點是,在這里只有返回值newCust才是在當前持久化上下文相關聯(lián)的BEAN,而做為參數(shù)傳進去的cust并不是,它可以只是一個簡單的脫離了EntityManager管理的類。
3,DELETE
DELETE顧名思義就是刪除的意思,當我們刪除一個實體的時候,我們標志了DELETE關聯(lián)的實體都會被相應的刪除。
Customer cust = entityManager.find(Customer.class, 1);
entityManager.remove(cust);
當我們刪除一個cust的時候,它相關聯(lián)的phone,address也會一并被刪除。
4,REFRESH
REFRESH就是更新的意思,它有點類似于MERGE,但是它是和MERGE相反的,我們MERGE的時候,會把當前實體的值合并到數(shù)據(jù)庫中,而當我們REFRESH的時候,卻是把據(jù)庫的最新值更新到我們的實體BEAN中。
Customer cust
;
entityManager.refresh(cust); // address would be refreshed too
在上面,如果address在數(shù)據(jù)庫中被別的程序更改了,那么當這句話調(diào)用結束之后,cust里面的address也跟著更新了,在這里,cust和address的數(shù)據(jù)不會被寫入數(shù)據(jù)庫,相反的,數(shù)據(jù)庫的最新值將被寫入到它們里面。當我們不需要把數(shù)據(jù)寫入數(shù)據(jù)庫,而只需要從數(shù)據(jù)庫里面取最新的時候,這個方法是很有用的。比如數(shù)據(jù)庫某些列是數(shù)據(jù)庫觸發(fā)某個事件自動更新的,而不需要我們自己去更新,就可以用這個,這個時候,最好不是在這一列上加如下注釋以確保此列數(shù)據(jù)不會被我們?nèi)藶榈馗模?br />
@Column (insertable=false, updatable=false...
5,ALL
ALL就是全部的意思,它表示以上四種關聯(lián)它都擁有。
其實并不是所有的場合都適合用關聯(lián),因為有些時候,一些數(shù)據(jù)的更新并不影響別的數(shù)據(jù),這個時候就不需要關聯(lián)了,比如,我們不希望多對多的時候,如果人改國籍不應該把原來的國家的實體刪掉吧。所以在我們使用關聯(lián)的時候,一定要想清楚,是不是實體之間有相輔相成的關系或者缺一不可的關系。其實使用關聯(lián)只是讓我們偷偷懶而已,因為它可以讓我們少寫一些相關的代碼,呵呵:)