實(shí)體bean
實(shí)體bean的角色
實(shí)體bean用來代表底層的對(duì)象。最常用的是用實(shí)體bean代表關(guān)系庫中的數(shù)據(jù)。一個(gè)簡單的實(shí)體bean可以定義成代表數(shù)據(jù)庫表的一個(gè)記錄,也就是每一個(gè)實(shí)例代表一個(gè)特殊的記錄。更復(fù)雜的實(shí)體bean可以代表數(shù)據(jù)庫表間關(guān)聯(lián)視圖。在實(shí)體bean中還可以考慮包含廠商的增強(qiáng)功能,如對(duì)象--關(guān)系映射的集成。
通常用實(shí)體類代表一個(gè)數(shù)據(jù)庫表比代表多個(gè)相關(guān)聯(lián)的表更簡單且更有效。反過來可以輕易地向?qū)嶓w類的定義中增加關(guān)聯(lián),這樣可以最大地復(fù)用cache并減小舊數(shù)據(jù)的表現(xiàn)。
實(shí)體bean和對(duì)話bean的比較
看起來會(huì)話bean好象沒什么用處,尤其對(duì)于數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用程序。當(dāng)然事實(shí)并不是這樣。因?yàn)閷?shí)體bean(譬如說)代表底層數(shù)據(jù)庫的一行,則實(shí)體bean實(shí)例和數(shù)據(jù)庫記錄間就是一對(duì)一的關(guān)系。因?yàn)槎鄠€(gè)客戶端必須訪問底層記錄,這意味著,不同于會(huì)話bean,客戶端必須共享實(shí)體bean。因?yàn)槭枪蚕淼?,所以?shí)體bean不允許保存每個(gè)客戶端的信息。會(huì)話bean允許保存客戶端的狀態(tài)信息,客戶端和會(huì)話bean實(shí)例間是一對(duì)一的。實(shí)體bean允許保存記錄的信息,實(shí)體bean實(shí)例和記錄間是一對(duì)一的。一個(gè)理想的情況是客戶端通過會(huì)話bean連接服務(wù)器,然后會(huì)話bean通過實(shí)體bean訪問數(shù)據(jù)庫。這使得既可以保存客戶端的信息又可以保存數(shù)據(jù)庫記錄的信息。
同時(shí)會(huì)話bean也不能提供在相同或不同的EJB類調(diào)用間進(jìn)行全局的事務(wù)控制。沒有會(huì)話bean,應(yīng)用程序開發(fā)者(客戶端開發(fā)者)就必須理解EJB類的事務(wù)要求,并使用客戶端的事務(wù)劃分來提供事務(wù)控制。EJB的主要好處就是應(yīng)用開發(fā)者不需知道EJB類的事務(wù)需求。一個(gè)會(huì)話bean可以代表一個(gè)商業(yè)操作,進(jìn)行事務(wù)控制,不需要客戶端進(jìn)行事務(wù)劃分。
Finder方法
通過home或remote interface創(chuàng)建和刪除bean的實(shí)例,對(duì)實(shí)體bean和會(huì)話bean來說有不同的含義。對(duì)會(huì)話bean來說,刪除意味著從容器中刪除,不能再使用,并且其狀態(tài)信息也丟失了。對(duì)于實(shí)體bean,刪除意味著底層數(shù)據(jù)庫記錄被刪除了。因此,一般不把刪除作為實(shí)體bean生命周期的一部分。
創(chuàng)建一個(gè)實(shí)體bean意味著一個(gè)記錄被插進(jìn)數(shù)據(jù)庫中。與刪除操作類似,創(chuàng)建操作通常也不作為實(shí)體bean生命周期的一部分??蛻舳嗽L問實(shí)體bean需 日業(yè)剿?3?薱reate()方法,一個(gè)實(shí)體bean的home interface還有finder方法??蛻舳诵枰鶕?jù)應(yīng)用程序的限制來識(shí)別一個(gè)特殊的數(shù)據(jù)庫記錄。例如:
public interface AccountHome extends EJBHome {
public Account findByFirstLast(String first, String last)
throws RemoteException,FinderException;
public Account findByAccountNumber(String acctNum)
throws RemoteException,FinderException;
}
當(dāng)客戶端調(diào)用home object的任何方法,容器把調(diào)用傳遞到實(shí)體bean的相應(yīng)方法中。
Public class myEntityBean implements EntityBean {
…
public Obejct ejbFindByFirstLast(String first, String last) {
//runs appropriate singleton SELECT statement
//returns primary key for selected row
}
public Obejct ejbFindByAccountNumber(String acctNum) {
//runs appropriate singleton SELECT statement
//returns primary key for selected row
}
}
一個(gè)較好的方法是把finder方法當(dāng)成數(shù)據(jù)庫的SELECT語句,而動(dòng)態(tài)SQL參數(shù)相當(dāng)于方法的參數(shù)。注意home interface中的finder方法向客戶端返回一個(gè)對(duì)EJBObject的遠(yuǎn)程引用。Bean中的Finder方法向容器返回一個(gè)唯一的標(biāo)識(shí)符,稱為主鍵。容器用這個(gè)主鍵實(shí)例化一個(gè)代表選定的記錄的EJBObject。不論如何實(shí)現(xiàn)finder方法,容器都用這個(gè)主鍵代表這個(gè)選定的記錄,由實(shí)體類來決定如何用唯一的標(biāo)識(shí)符來代表記錄。
由可能一個(gè)finder方法得到滿足SELECT語句條件的多個(gè)記錄。這種情況下bean的finder方法返回一個(gè)主鍵的枚舉類型。Home interface的Finder方法定義成向客戶端返回EJBObject引用的枚舉類型。
Public interface AccountHome extends EJBHome {
…
public Enumeration findByCompany(String companyName)
throws RemoteException,FinderException;
}
public class myEntityBean implements EntityBean {
…
public Enumeration ejbFindByCompany(String companyName) {
//runs appropriate SELECT statement
//returns an Enumeration of primary keys
}
}
主鍵
主鍵這個(gè)詞有可能被曲解。把它理解為唯一的標(biāo)識(shí)符更恰當(dāng)些。當(dāng)實(shí)體bean代表一個(gè)數(shù)據(jù)庫記錄時(shí),主鍵可能是該記錄的組合鍵。對(duì)于每個(gè)實(shí)體bean的實(shí)例,有一個(gè)相應(yīng)的EJBObject.當(dāng)一個(gè)EJBObject與一個(gè)實(shí)體bean實(shí)例對(duì)應(yīng)時(shí),該實(shí)例的主鍵保存在EJBObject中。
這時(shí)說該實(shí)體bean的實(shí)例有一個(gè)標(biāo)識(shí)符。當(dāng)客戶端調(diào)用home object的finder方法時(shí),容器會(huì)用沒有標(biāo)識(shí)符的實(shí)體bean的實(shí)例來執(zhí)行這個(gè)請(qǐng)求。容器可能為此維持一個(gè)甚至多個(gè)匿名的實(shí)例。不論如何實(shí)現(xiàn)finder方法,都必須向容器返回底層數(shù)據(jù)的主鍵,如數(shù)據(jù)庫的記錄。如果多個(gè)記錄滿足條件,那么就返回多個(gè)主鍵。當(dāng)容器得到主鍵后,它會(huì)用該主鍵初始化一個(gè)EJBObject.容器也可以初始化一個(gè)與每個(gè)EJBObject關(guān)聯(lián)的實(shí)體bean的實(shí)例。因?yàn)榈讓佑涗浀臉?biāo)識(shí)符在EJBObject中保存,因此在bean實(shí)例中沒有狀態(tài)。因此,容器可以在EJBObject上調(diào)用商業(yè)方法時(shí)再實(shí)例化bean,以節(jié)省內(nèi)存資源。
當(dāng)finder方法向容器返回主鍵時(shí),容器首先會(huì)檢查該主鍵的EJBObject是否已經(jīng)存在。如果該主鍵的EJBObject已經(jīng)存在,那么容器不會(huì)創(chuàng)建一個(gè)新的EJBObject,而是向客戶端返回這個(gè)已存在的EJBObject的引用。這樣就保證了每個(gè)記錄只有一個(gè)EJBObject的實(shí)例,所有的客戶端共享EJBObject.
主鍵只是在該類中唯一地標(biāo)識(shí)bean的實(shí)例,容器負(fù)責(zé)保證其范圍。應(yīng)該明確finder方法只是從數(shù)據(jù)庫中取出數(shù)據(jù)的主鍵,而不包含其它的數(shù)據(jù)項(xiàng)。也可能調(diào)用finder方法后不產(chǎn)生任何實(shí)體bean的實(shí)例,只產(chǎn)生包含該主鍵的EJBObject,當(dāng)客戶端調(diào)用EJBObject的方法時(shí)在產(chǎn)生并導(dǎo)入實(shí)體bean的實(shí)例。 Home object保證客戶端可以訪問以下方法:
public myRem findByPrimaryKey(Obejct key) throws …;
EJBObject提供以下方法的一個(gè)實(shí)現(xiàn):
Public Object getPrimaryKey();
客戶端能在任何時(shí)候獲得實(shí)體bean的主鍵,并且以后可以使用該主鍵通過home interface重建對(duì)實(shí)體的引用。主鍵類的類型在部署描述符中指定。Bean開發(fā)者可以用任何類類型來表示主鍵。唯一的要求是類必須實(shí)現(xiàn)serializable,因?yàn)橹麈I可能在客戶和服務(wù)器間傳遞。
如對(duì)本文有疑問,請(qǐng)?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會(huì)為你解答?。?點(diǎn)擊進(jìn)入論壇