EJB設計模式5 (轉)

gugu99發表於2008-07-11
EJB設計模式5 (轉)[@more@]

 

就像我們在設計4中看到的, Entity Bean的實現大小被縮減到在Create(), getData()
and setData()方法中的僅僅幾行,不管CMP欄位的數目.
下一步是建模公司和僱員的Entity Beans,這個有點繁瑣而且建議讀者先對borland
公司的的OR Map和高階CMP有所瞭解.
對這個關係建模根本不需要對結構的程式碼變化,然而Entity Beans實現類需要一點點
修改來反映兩個實體間的關係,鑑於此Deployment Descriptor需要有小的修改.
象以前, Entity Bean從結構繼承,下面是公司Entity Bean的程式碼片段:
public class CompanyBean extends CompanyStruct
implements EntityBean {
EntityContext entityContext;
// CMP for all fields in the CompanyStruct
public .util.Collection employees; //one-to-many
//rest of the code including getData() and setData()
public java.util.Collection getEmployees() {
return employees;
}
}
下面是僱員Entity Bean的程式片段:
public class EmployeeBean extends EmployeeStruct
implements EntityBean {
EntityContext entityContext;
//CMP for all fields in EmployeeStruct EXCEPT
//the comId
public Company company;//remote reference to company
}
在上面的程式片段中,僱員Entity Bean從僱員結構繼承,僱員結構本身有
一個欄位comId表示僱員和公司之間的的外來鍵,在所有的前面的設計模式中,
這個欄位是CMP的.而在設計模式5中這個欄位用在Deployment Descriptor中
un-checking的方法從CMP中去掉.而對公司Entity Bean的引用現在是CMP的.
現在的問題是怎麼在getData()和SetData()方法中公司Entity Bean的引用,
當這些方法只get和set comId(在設計模式上下文中沒有被CMP)的值.
簡單的說,過程的結構沒有變化並且欄位comId(不再CMP)在RPC中被複製到
Entity Bean和從Entity Bean複製出來.需要的是對公司Entity Bean的遠端
引用在必須被寫入和從資料庫讀出時更新.我們需要用ejbLoad()和ejbStore()
方法在Entity Bean實現類中為我們完成這項工作.
在僱員Entity Bean中的ejbLoad()方法的程式碼片段如下:
public void ejbLoad() {
try {
comId=(company ==
null)?null:(Integer)company.getPrimaryKey();
} catch (Exception e) {
//throw some runtime exception (e.g. EJBException)
}
}
以上程式碼幾乎不需要解釋.當資料被從資料庫中讀出(在事務的開始時候),
comId(不是CMP)欄位在僱員Entity Bean被set.因此當getData()方法被時,
返回的結構將包含正確地comId的值.
在僱員Entity Bean中的ejbStore()方法如下:
public void ejbStore() {
try {
company = (comId ==
null)?null:beanGlossary.getCompanyHome().finyPrimary
Key(comId);
} catch (Exception e) {
//throw some runtime exception (e.g. EJBException)
}
}
ejbStore()在事務結束當資料被寫入資料庫時被呼叫.在這種情況下,comId的值
被修改(透過呼叫setData方法),this必須被寫到資料庫中.在上面方法中的程式碼
把comId轉化成公司的遠端引用.(畢竟comId是公司Entity Bean的主鍵).
使用空check的原因是資料庫不能存空值(表之間的弱引用),並且這些同樣需要建模.
任何情況下,用java對基本型別的封裝要比使用基本型別自己好,因為他們能
存空值而且易於轉換成其他形式.
上面的BeanGlossary類的程式碼片斷容易引起一些混淆.
這實際上是一個捕獲EJB的lookup的utility類(一個無狀態session bean),
在entity bean和有狀態session bean的情況下,Home介面的lookup是被緩衝的.
在無狀態session bean的情況下,Remote介面是被緩衝的(作為ejb規範1.1的一部分,
一個SLSB在Home介面中呼叫的create()是不被的).
透過在上面上下文的緩衝,我們意思是第一個請求是被lookup的.隨後的呼叫是得到
已經在引用中初始化的home介面或remote介面.
BeanGlossarySB utility類的程式碼片段如下:
public class BeanGlossarySB implements SessionBean {
private Context context = null;
public javax.naming.Context getContext() throws
NamingException {
if (context == null)
context = new javax.naming.InitialContext();
return context;
}
// Company
private CompanyHome companyHome = null;
public CompanyHome getCompanyHome() throws
NamingException {
if (companyHome == null)
companyHome = ((CompanyHome)
javax..PortableRemote.narrow(
getContext().lookup("java:comp/env/ejb/Company"),
CompanyHome.class));
return companyHome;
}
// rest of the EJBs
}
在設計模式5中,我們沒有處理Entity Bean的Home介面.
在僱員Entity Bean的情況下, 會有一個finder元素在
findEmployeesByCompany(Company pCompany)的幾行中,
這將會返回僱員遠端引用的集合. 在公司Entity Bean 中的Deployment
Descriptor map了在上面定義的finder元素的僱員集合.
這樣,在公司Entity Bean中的方法getEmployees()在remote介面中的呼叫
返回需要的與那家公司相聯絡的遠端引用的僱員的集合.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1007121/,如需轉載,請註明出處,否則將追究法律責任。

相關文章