J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù).doc_第1頁
J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù).doc_第2頁
J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù).doc_第3頁
J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù).doc_第4頁
J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù).doc_第5頁
已閱讀5頁,還剩22頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

J2EE應(yīng)用程序BMP實現(xiàn)實體Bean的編碼技術(shù)數(shù)據(jù)是大多數(shù)商業(yè)應(yīng)用程序的核心(這個好像是廢話,沒有數(shù)據(jù)程序也只能玩玩了)。在J2EE應(yīng)用程序中,實體Bean表示存儲在數(shù)據(jù)庫中的商業(yè)實體。如果用BMP實現(xiàn)實體Bean,你必須自己編寫數(shù)據(jù)庫訪問代碼。雖然寫這些代碼是附加的責(zé)任,但是因此你可以更靈活的控制實體Bean訪問數(shù)據(jù)庫的行為(當(dāng)然這得你自己愿意才行)。本章討論BMP實現(xiàn)實體Bean的編碼技術(shù)。內(nèi)容:1SavingsAccountEJB實體Bean類Home接口Remote接口運行該例子2用deploytool部署B(yǎng)MP實現(xiàn)的實體Bean3為BMP映射表間關(guān)系一對一關(guān)系一對多關(guān)系多對多關(guān)系4BMP的主鍵主鍵類實體Bean中的主鍵獲取主鍵5處理異常一SavingsAccountEJB本例中的實體Bean表示一個樣本銀行賬號。SavingsAccountEJB的狀態(tài)信息保存在一個關(guān)系數(shù)據(jù)庫的savingaccount表中。創(chuàng)建該表的SQL語句如下:CREATE TABLE savingsaccount (id VARCHAR(3) CONSTRAINT pk_savingsaccount PRIMARY KEY, firstname VARCHAR(24), lastname VARCHAR(24), balance NUMERIC(10,2); SavingsAccountEJB由三個文件組成:l 實體Bean類(SavingsAccountBean)l Home接口(SavingsAccountHome)l Remote接口(SavingsAccount)本例應(yīng)用程序還包括下面的兩個類:l 一個異常類InsufficientBalanceExceptionl 一個客戶端類SavingsAccountClient該例子的源代碼文件在j2eetutorial/examples/src/ejb/savingsaccount 目錄下,可以在j2eetutorial/examples 目錄下用ant savingsaccount 來編譯這些代碼。一個樣本SavingsAccountApp.ear文件放在j2eetutorial/examples/ears 目錄下。實體Bean類(SavingsAccountBean)SavingsAccount是本例中的實體Bean類。從它的代碼可以看出BMP實現(xiàn)實體Bean的基本要求。首先實現(xiàn)一下接口和方法:l EntityBean接口l 大于等于零對的ejbCreate和ejbPostCreate方法(實體Bean可以沒有ejbCreate方法,只有查找方法,但是不能兩者都沒有)l 查找(Finder)方法l 商業(yè)方法l Home方法(這里的Home方法不好理解,如果是指生命周期方法,應(yīng)該包含ejbcreate等方法)另外它還有如下的一些特征:l 該類訪問屬性為publicl 該類不可以被定義為abstract或者finall 該類包含一個空構(gòu)造函數(shù)l 該類不可以實現(xiàn)finalize方法EntityBean接口該接口也繼承至EnterpriseBean接口(EnterpriseBean接口是SessionBean和EntityBean共同的父接口,它繼承至Serializable接口,沒有任何方法)。EntityBean定義一些方法,如ejbActive、ejbLoad和ejbStore等等,你必須在實體Bean類里實現(xiàn)它們。EntityBean接口的定義如下:package javax.ejb;import java.rmi.RemoteException;/ Referenced classes of package javax.ejb:/ EnterpriseBean, EJBException, RemoveException, EntityContextpublic interface EntityBean extends EnterpriseBean public abstract void setEntityContext(EntityContext entitycontext) throws EJBException, RemoteException; public abstract void unsetEntityContext() throws EJBException, RemoteException; public abstract void ejbRemove() throws RemoveException, EJBException, RemoteException; public abstract void ejbActivate() throws EJBException, RemoteException; public abstract void ejbPassivate() throws EJBException, RemoteException; public abstract void ejbLoad() throws EJBException, RemoteException; public abstract void ejbStore() throws EJBException, RemoteException;ejbCreate方法當(dāng)客戶端調(diào)用create方法后,EJB容器調(diào)用對應(yīng)的ejbCreate方法。實體Bean中典型的ejbCreate方法完成如下工作:l 將實體狀態(tài)(表述實體Bean的屬性字段)插入數(shù)據(jù)庫l 初始化實例變量,就是對實體Bean的屬性字段賦值l 返回主鍵本例中SavingsAccountBean的ejbCreate方法調(diào)用私有方法insertRow來將實體狀態(tài)插入數(shù)據(jù)庫,insertRow方法向數(shù)據(jù)庫發(fā)出一條INSERT的SQL命令。下面是ejbCreate方法的代碼:public String ejbCreate(String id, String firstName, String lastName, BigDecimal balance) throws CreateException if (balance.signum() = -1) throw new CreateException (A negative initial balance is not allowed.); try insertRow(id, firstName, lastName, balance); catch (Exception ex) throw new EJBException(ejbCreate: + ex.getMessage(); this.id = id; this.firstName = firstName; this.lastName = lastName; this.balance = balance; return id;雖然SavingsAccountBean類只有一個ejbCreate方法,但是一個企業(yè)Bean可以有多個ejbCreate方法。例如前一章CartEJB的例子。編寫實體Bean的ejbCreate方法許要遵循如下規(guī)則:l 訪問權(quán)修飾符必須是publicl 返回值類型必須是主鍵類l 參數(shù)類型必須符合RMI調(diào)用規(guī)則l 該方法不可以聲明為final或者staticthrows子句要包含javax.ejb.CreateException異常,通常遇到非法參數(shù)ejbCreate方法會拋出該異常。如果ejbCreate方法因為存在使用相同主鍵的其他實體而無法創(chuàng)建實體,將拋出javax.ejb.DuplicateKeyException異常,它是CreateException的子類。如果客戶端捕獲CreateException或者DuplicateKeyException異常,就表示實體創(chuàng)建失敗。實體Bean的狀態(tài)數(shù)據(jù)可能被J2EE服務(wù)器不知道的其他應(yīng)用程序直接插入到數(shù)據(jù)庫里。例如,你可以直接用SQL語句在數(shù)據(jù)庫工具中插入一行到savingsaccount表里。雖然該行對應(yīng)的實體Bean沒有被ejbCreate方法創(chuàng)建,但客戶端仍然可以找到該行對應(yīng)的實體Bean(不用說,這里當(dāng)然是用ejbFinder方法了,下面會介紹)。EjbPostCreate方法對每一個ejbCreate方法,你都必須在實體Bean中寫一個對應(yīng)的ejbPostCreate方法。因為EJB容器在調(diào)用ejbCreate方法后接著就調(diào)用ejbPostCreate方法。跟ejbCreate方法不同的是,ejbPostCreate方法可以調(diào)用EntityContext接口的getPrimaryKey和getEJBObject方法(在前一章的傳遞企業(yè)Bean對象的引用一節(jié)討論過)。EjbPostCreate方法大部分情況下什么事也不干。EjbPostCreate方法聲明必須符合一下要求:l 參數(shù)數(shù)量類型聲明順序必須跟對應(yīng)的ejbCreate方法相同l 必須聲明為publicl 不能聲明為final或者staticl 返回值必須是voidthrows子句要包含javax.ejb.CreateException異常。ejbRemove方法客戶端調(diào)用remove方法來刪除實體Bean。該調(diào)用會引發(fā)EJB容器調(diào)用ejbRemove方法,ejbRemove方法從數(shù)據(jù)庫中刪除實體狀態(tài)對應(yīng)的數(shù)據(jù)。SavingsAccountBean的ejbRemove方法調(diào)用deleteRow私有方法向數(shù)據(jù)庫發(fā)送一條DELETE的SQL命令。代碼如下:public void ejbRemove() try deleteRow(id); catch (Exception ex) throw new EJBException(ejbRemove: + ex.getMessage(); 如果ejbRemove方法遇到系統(tǒng)問題就拋出javax.ejb.EJBException異常。如果遇到一個應(yīng)用程序異常就怕拋出javax.ejb.RemoveException異常。要區(qū)分系統(tǒng)異常和應(yīng)用程序異常請參考異常處理一節(jié)。實體Bean狀態(tài)數(shù)據(jù)也可能被直接從數(shù)據(jù)庫中刪除。當(dāng)用SQL語句刪除數(shù)據(jù)庫中實體Bean狀態(tài)數(shù)據(jù)對應(yīng)的行時,實體Bean也會被刪除。ejbLoad和ejbStore方法如果EJB容器要同步實體Bean的屬性子段和數(shù)據(jù)庫中對應(yīng)的數(shù)據(jù)就調(diào)用這兩個方法。顧名思義,ejbLoad方法從數(shù)據(jù)庫中取出數(shù)據(jù)并刷新屬性子段的值,ejbStore方法把屬性子段值寫入數(shù)據(jù)庫??蛻舳瞬荒苷{(diào)用這兩個方法。如果商業(yè)方法在一個事務(wù)環(huán)境中執(zhí)行,EJB容器會在該方法執(zhí)行前調(diào)用ejbLoad,并在該方法執(zhí)行完后立即調(diào)用ejbStore方法。這樣你不必在商業(yè)方法中調(diào)用這兩個方法來刷新和存儲實體Bean數(shù)據(jù)。SavingsAccountBean依賴容器同步實體和數(shù)據(jù)庫的數(shù)據(jù),所以商業(yè)方法應(yīng)該在事務(wù)環(huán)境中執(zhí)行。如果ejbLoad和ejbStore方法不能在數(shù)據(jù)庫中找到實體的數(shù)據(jù)就會拋出javax.ejb.NosuchEntityException異常,它是EJBException的子類。因為它的父類是RutimeException的子類,所以你不必將該異常加到throws子句中。該異常在返回客戶端前被容器封裝進RemoteException的一個實例。在SavingsAccountBean類中,ejbLoad調(diào)用LoadRow私有方法,后者向數(shù)據(jù)庫發(fā)送一條SELECT的SQL命令并將讀出的數(shù)據(jù)賦給SavingsAccountBean的屬性字段。EjbStore調(diào)用storeRow私有方法,后者用UPDATE的SQL命令將SavingsAccountBean的屬性字段值存入數(shù)據(jù)庫。下面是這兩個方法的代碼:public void ejbLoad() try loadRow(); catch (Exception ex) throw new EJBException(ejbLoad: + ex.getMessage(); public void ejbStore() try storeRow(); catch (Exception ex) throw new EJBException(ejbStore: + ex.getMessage(); 查找方法(Finder)查找方法允許客戶端查找實體Bean。SavingsAccountClient可以通過三個查找方法查找實體Bean:SavingsAccount jones = home.findByPrimaryKey(836);.Collection c = home.findByLastName(Smith);.Collection c = home.findInRange(20.00, 99.00); 對每一個客戶端可用的查找方法,實體Bean類必須事先一個對應(yīng)的ejbFind為前綴的方法。SavingsAccountBean中對應(yīng)上面findByLastName方法的ejbFindByLastNamef方法代碼如下:public Collection ejbFindByLastName(String lastName) throws FinderException Collection result; try result = selectByLastName(lastName); catch (Exception ex) throw new EJBException(ejbFindByLastName + ex.getMessage(); return result;查找方法的實現(xiàn)細(xì)節(jié)用應(yīng)用程序決定,例如上例的ejbFindByLastName和ejbFindInRange方法的命名都是很隨意的。但是ejbFindByPrimaryKey方法命名不能隨意,就像它的名字所暗示的,該方法有一個用來查找實體Bean的主鍵類型的參數(shù)。SavingsAccountBean類中,主鍵是id子段。下面是SavingsAccountBean的ejbFindByPrimaryKey方法的實現(xiàn)代碼:public String ejbFindByPrimaryKey(String primaryKey) throws FinderException boolean result; try result = selectByPrimaryKey(primaryKey); catch (Exception ex) throw new EJBException(ejbFindByPrimaryKey: + ex.getMessage(); if (result) return primaryKey; else throw new ObjectNotFoundException (Row for id + primaryKey + not found.); 上面的實現(xiàn)也許對你來說有點陌生,因為它的參數(shù)和返回值都是主鍵類。不過,記住客戶端并不直接調(diào)用ejbFindByPrimaryKey方法,而是由EJB容器代勞的??蛻舳酥荒苷{(diào)用在Home接口中聲明的findByPrimaryKey方法。下面總結(jié)一下BMP實現(xiàn)實體Bean的查找方法的規(guī)則:l 必須實現(xiàn)ejbFindByPrimaryKey方法l 方法名必須用ejbFind做前綴l 方法不能用final或者static方法l 如果BMP實現(xiàn)Remote接口組中的方法,則方法的參數(shù)和返回值類型必須是符合RMI API調(diào)用的合法類型l 返回類型必須是主鍵類或者主鍵類的集合Throws字句要包括javax.ejb.FinderException。如果查找方法返回一個主鍵類對象但是被查找的實體不存在,該方法將拋出javax.ejb.ObjectNotFoundException,該異常是javax.ejb.FinderException的子類。如果查找方法返回主鍵類對象集合,而且也沒有符合要求的實體,則該方法返回空集合。商業(yè)方法商業(yè)方法處理你想封裝在實體Bean中的商業(yè)邏輯。一般商業(yè)方法并不訪問數(shù)據(jù)庫,以使你可以把商業(yè)邏輯和數(shù)據(jù)庫訪問代碼分離。SavingsAccountBean包含以下一些商業(yè)方法:public void debit(BigDecimal amount) throws InsufficientBalanceException if (pareTo(amount) = -1) throw new InsufficientBalanceException(); balance = balance.subtract(amount);public void credit(BigDecimal amount) balance = balance.add(amount); public String getFirstName() return firstName; public String getLastName() return lastName; public BigDecimal getBalance() return balance;SavingsAccountClient客戶端這樣吊用這些商業(yè)方法:BigDecimal zeroAmount = new BigDecimal(0.00);SavingsAccount duke = home.create(123, Duke, Earl, zeroAmount);.duke.credit(new BigDecimal(88.50);duke.debit(new BigDecimal(20.25);BigDecimal balance = duke.getBalance(); 會話Bean和實體Bean的商業(yè)方法的簽名規(guī)則是相同的:l 方法名不能和EJB體系定義的方法名沖突,比如商業(yè)方法不能命名為:ejbCreate或者ejbActivatel 訪問修飾必須是publicl Remote接口租中定義的方法的參數(shù)和返回值必須是RMI API規(guī)范的合法類型Throws子句沒有特殊要求。例如debit方法拋出InsufficientBalaceException自定義異常。為了捕獲系統(tǒng)異常,商業(yè)方法可以拋出javax.ejb.EJBException。Home方法Home方法包含那些應(yīng)用于一個特定企業(yè)Bean類的所有實例的商業(yè)邏輯。正好和只應(yīng)用于由主鍵標(biāo)志的企業(yè)Bean單個實例的商業(yè)方法相反。Home方法調(diào)用期間,企業(yè)Bean實例不僅沒有唯一的標(biāo)志主鍵,也不具備表示一個商業(yè)實體的狀態(tài)。因此,Home方法不可以訪問企業(yè)Bean的持久性字段(企業(yè)Bean中的實例變量)。(對于CMP,Home方法也不能訪問關(guān)系字段。)Home方法查找到企業(yè)Bean的實例的集合然后通過集合的迭代器調(diào)用商業(yè)方法是實現(xiàn)Home方法的典型做法。SavingsAccountBean類的ejbHomeChargeForLowBalance就是這樣做的。該方法對余額少于某個特定數(shù)值的賬戶收取服務(wù)費,首先調(diào)用findInRange方法得到符合條件所有的賬戶,它返回一個SavingAccount實現(xiàn)類實例的集合,然后通過集合的迭代器訪問這些遠(yuǎn)程接口對象,在檢查了余額之后調(diào)用debit商業(yè)方法收取費用。下面是代碼:public void ejbHomeChargeForLowBalance( BigDecimal minimumBalance, BigDecimal charge) throws InsufficientBalanceException try SavingsAccountHome home = (SavingsAccountHome)context.getEJBHome(); Collection c = home.findInRange(new BigDecimal(0.00), minimumBalance.subtract(new BigDecimal(0.01); Iterator i = c.iterator(); while (i.hasNext() SavingsAccount account = (SavingsAccount)i.next(); if (account.getBalance().compareTo(charge) = 1) account.debit(charge); catch (Exception ex) throw new EJBException(ejbHomeChargeForLowBalance: + ex.getMessage(); 該方法在Home接口中對應(yīng)的定義為chargeForLowBalance(稍后的Home方法定義將具體介紹)??蛻舳丝梢酝ㄟ^該接口訪問Home方法:SavingsAccountHome home;.home.chargeForLowBalance(new BigDecimal(10.00), new BigDecimal(1.00);綜上所述,實體Bean類中Home方法的實現(xiàn)要遵循以下規(guī)則:l 方法名必須以ejbHome開頭l 訪問修飾符必須是publicl 方法不可以是static方法根據(jù)應(yīng)用程序邏輯確定throws子句,throws子句中不能包含java.rmi.RemoteException異常。數(shù)據(jù)庫訪問表5-1列出了SavingsAccountBean的數(shù)據(jù)庫訪問操作。商業(yè)方法并不在表中,因為它們不訪問數(shù)據(jù)庫,它們只是更新企業(yè)Bean的持久性子段,這些字段的值會在EJB容器調(diào)用ejbStore方法時被寫入數(shù)據(jù)庫。但是這并不是強制的規(guī)則,你也可以在商業(yè)方法中直接訪問數(shù)據(jù)庫來存取數(shù)據(jù),這要根據(jù)你的應(yīng)用程序的具體需要來決定。訪問數(shù)據(jù)庫前你必須先得到數(shù)據(jù)庫的連接,關(guān)于數(shù)據(jù)庫連接的更多信息將在16章討論。表 5-1 SavingsAccountBean中的SQL語句方法SQL 語句ejbCreateINSERTejbFindByPrimaryKeySELECTejbFindByLastNameSELECTejbFindInRangeSELECTejbLoadSELECTejbRemoveDELETEejbStoreUPDATEHome接口Home接口定義了讓客戶端創(chuàng)建和查找實體Bean的方法。本例中SavingsAccountHome接口的實現(xiàn)如下:import java.util.Collection;import java.math.BigDecimal;import java.rmi.RemoteException;import javax.ejb.*;public interface SavingsAccountHome extends EJBHome public SavingsAccount create(String id, String firstName, String lastName, BigDecimal balance) throws RemoteException, CreateException; public SavingsAccount findByPrimaryKey(String id) throws FinderException, RemoteException; public Collection findByLastName(String lastName) throws FinderException, RemoteException; public Collection findInRange(BigDecimal low, BigDecimal high) throws FinderException, RemoteException; public void chargeForLowBalance(BigDecimal minimumBalance, BigDecimal charge) throws InsufficientBalanceException, RemoteException; 定義create方法create方法的定義規(guī)則:l 必須和企業(yè)Bean類中對應(yīng)的ejbCreate方法有相同的參數(shù)數(shù)量、類型和排列順序。就是要為每個Home中的定義的可用create方法在企業(yè)Bean中實現(xiàn)對應(yīng)的ejbCreate方法。l 返回企業(yè)Bean的遠(yuǎn)程接口類型l throws子句包括對應(yīng)的ejbCreate方法和ejbPostCreate方法的throws子句中出現(xiàn)的所有異常,另外還要包括javax.ejb.CreateExceptionl 如果方法是在Home接口而不是在LocalHome接口中定義的則throws子句必須包括java.rmi.RemoteException異常定義查找方法跟create的規(guī)則相似,Home接口中的每個查找方法都對應(yīng)一個企業(yè)Bean類中的一個查找方法。Home接口中的查找方法必須以find開頭,企業(yè)Bean類中對應(yīng)的方法以ejbFind開頭。本例中SavingsAccountHome接口定義的findByLastName對應(yīng)的SavingsAccountBean類的方法為ejbFindByLastName方法。總結(jié)一下Home接口中的方法必須符合一下條件:l 參數(shù)個數(shù)類型和順序必須和對應(yīng)的ejbFind方法相同l 返回實體Bean遠(yuǎn)程接口類型,或是遠(yuǎn)程接口類型的集合l throws字據(jù)除了包括對應(yīng)的ejbFind方法的throws子句中出現(xiàn)的異常外,還要包括javax.ejb.FinderExceptionl 不是在Local Home接口中定義的方法throws子句還要包括java.rmi.RemoteExceotion異常定義Home方法Home接口中的每個Home方法都在實體Bean類中有一個對應(yīng)的方法,這些方法的命名沒有特殊的前綴,相反對應(yīng)的實體Bean類中的方法要以ejbHome開頭。如本例中SavingsAccountBean類中前面提到的ejbHomeChargeForLowBalance方法,在Home接口中的對應(yīng)方法名為chargeForLowBalance。除了Home方法不拋出FinderException,它的簽名規(guī)則和查找方法是一樣的。Remote接口Remote接口繼承javax.ejb.EJBObject接口,定義遠(yuǎn)程客戶端訪問的商業(yè)方法。本例中SavingsAccount遠(yuǎn)程接口定義如下:import javax.ejb.EJBObject;import java.rmi.RemoteException;import java.math.BigDecimal;public interface SavingsAccount extends EJBObject public void debit(BigDecimal amount) throws InsufficientBalanceException, RemoteException; public void credit(BigDecimal amount) throws RemoteException; public String getFirstName() throws RemoteException; public String getLastName() throws RemoteException; public BigDecimal getBalance() throws RemoteException; 會話Bean和實體Bean的遠(yuǎn)程方法的定義規(guī)則是相同的,這里再重復(fù)一下:l 每個方法在企業(yè)Bean類中都必須有對應(yīng)的方法l 方法簽名必須和企業(yè)Bean類中的對應(yīng)方法相同l 參數(shù)和返回值必須是符合RMI規(guī)范的類型l throws子句企業(yè)Bean類對應(yīng)方法的throws子句的基礎(chǔ)上添加java.rmi.RemoteException而Local接口有所不同:l 參數(shù)和返回值不需要是RMI合法類型l throws子句不需要包括java.rmi.RemoteException運行本例子配置數(shù)據(jù)庫本例使用Cloundscape數(shù)據(jù)庫,該數(shù)據(jù)庫軟件被包括在J2EE SDK包里。1. 啟動數(shù)據(jù)庫。在命令方式下執(zhí)行如下命令cloudscape start關(guān)閉命令為:cloudscape -stop2. 創(chuàng)建savingsaccount表a) 進入j2eetutorial/examples 目錄b) 執(zhí)行ant create-savingsaccount-table 命令你也可以用其他數(shù)據(jù)庫來運行本例(要是J2EE服務(wù)器支持的數(shù)據(jù)庫)。在其他數(shù)據(jù)庫中創(chuàng)建該表要執(zhí)行j2eetutorial/examples/sql/savingsaccount.sql 腳本文件。部署應(yīng)用程序1 用deploy工具打開j2eetutorial/examples/ears/SavingsAccountApp.ear 文件2 執(zhí)行ToolsDeploy菜單命令部署。確定Introduction對話中你選中了Return Client JAR復(fù)選框運行客戶端1 在命令方式下進入j2eetutorial/examples/ears 目錄2 設(shè)置APPPATH環(huán)境變量為SavingsAccountAppClient.jar 所在目錄3 執(zhí)行以下命令(只有一條命令,有點長):runclient -client SavingsAccountApp.ear -name SavingsAccountClient textauth4 在登錄提示符下輸入用戶名guest,密碼guest1235 這一步什么也不做,看看結(jié)果: balance = 68.25 balance = 32.55 456: 44.77 730: 19.54 268: 100.07 836: 32.55 456: 44.77 4.00 7.00二用deploytool部署B(yǎng)MP實現(xiàn)的實體Bean第4章介紹了創(chuàng)建一個會話Bean包的步驟,創(chuàng)建實體Bean包的步驟相似,但是有以下不同:1. 在新建企業(yè)Bean向?qū)В∟ew Enterprise Bean)中,指定企業(yè)Bean類型和持久性管理類型a) 在General對話框中,選定Entity單選項b) 在Entity Settings對話框中,選定Bean-Managed Persistence2. 在Resource Refs頁,指定企業(yè)Bean引用的資源工廠。這些設(shè)置使企業(yè)Bean可以訪問數(shù)據(jù)庫。具體的設(shè)置信息參考用deploytool工具配置資源引用一節(jié)3. 部署前,檢查你的JNDI名是否都是對的a) 從樹中選擇要部署的應(yīng)用程序b) 選擇JNDI Names頁三為BMP映射表間關(guān)系在關(guān)系數(shù)據(jù)庫中,數(shù)據(jù)表可以通過共同的列建立關(guān)系。數(shù)據(jù)庫的關(guān)系影響了他們對應(yīng)的實體Bean的設(shè)計。本節(jié)分以下幾類討論實體Bean如何映射數(shù)據(jù)庫中的表間關(guān)系l 一對一l 一對多l(xiāng) 多對多一對一關(guān)系一對一關(guān)系中一個表1的一行數(shù)據(jù)只對應(yīng)于表2的一行數(shù)據(jù),表2的一行數(shù)據(jù)也只對應(yīng)表1的一行數(shù)據(jù)。例如:一個倉庫應(yīng)用程序中,儲藏箱(storagebin)表和小物件(widget)表就可能是一對一關(guān)系。這個應(yīng)用程序要為物理倉庫中每個儲藏箱只裝一個小物件并且每個小物件也只能裝在一個儲藏箱中建立邏輯模型。圖5-1說明了兩個表的關(guān)系。因為storagebinid字段可以唯一確定storagebin表中的一行,它是這個表的主鍵。widgetid是widget表的主鍵。storagebin表也有一個widgetid字段來關(guān)聯(lián)兩張表的數(shù)據(jù)。通過在storagebin表中引用widget表的主鍵,可以確定一個物件存儲在倉庫中的哪個儲存箱中。因為storagebin中widget字段引用其他表的主鍵,所以它是一個外鍵。(本章的圖例中用PK表示主鍵,F(xiàn)K表示外鍵。)圖 5-1 一對一關(guān)系 一般子表包含一個匹配父表數(shù)據(jù)的外鍵。子表storagebin中的外鍵widgetid的值依賴于父表widget的主鍵值。如果storagebin表中有一行的widgetid值為344,那么widget表中一定有一行數(shù)據(jù)的widgetid也是344。在設(shè)計數(shù)據(jù)庫應(yīng)用程序時,你必須保證子表和父表之間的依賴關(guān)系正確無誤。有兩種方法可以實現(xiàn)這種保證:在數(shù)據(jù)庫中定義參照約束或者在應(yīng)用程序中編碼檢查。本例中storagebin表定義了一個參照約束fk_widgetid:CREATE TABLE storagebin (storagebinid VARCHAR(3) CONSTRAINT pk_storagebin PRIMARY KEY, widgetid VARCHAR(3), quantity INTEGER, CONSTRAINT fk_widgetid FOREIGN KEY (widgetid) REFERENCES widget(widgetid);下面講到的例子的源文件可以在j2eetutorial/examples/src/ejb/storagebin目錄下找。在j2eetutorial/examples目錄下執(zhí)行storagebin命令編譯這些文件。StorageBinApp.ear樣本文件放在j2eetutorial/examples/ears目錄下。StorageBinBean和WidgetBean類文件實現(xiàn)了storagebin表和widget表之間的一對一關(guān)系。StorageBinBean類為storagebin表中包括外鍵widgetid的所有列生命了對應(yīng)的實例變量:private String storageBinId;private String widgetId;private int quantity; ejbFindByWidgetId方法返回跟傳入?yún)?shù)widgetId值匹配的storageBinId值:public String ejbFindByWidgetId(String widgetId) throws FinderException String storageBinId; try storageBinId = selectByWidgetId(widgetId); catch (Exception ex) throw new EJBException(ejbFindByWidgetId: + ex.getMessage(); if (storageBinId = null) throw new ObjectNotFoundException (Row for widgetId + widgetId + not found.); else return storageBinId; ejbFindByWidgetId方法通過調(diào)用selectByWidgetId方法來得到數(shù)據(jù)庫的查詢結(jié)果(這種做法的好處是將商業(yè)方法和數(shù)據(jù)庫操作方法分開,以使商業(yè)邏輯盡量的獨立于數(shù)據(jù)庫操作):private String selectByWidgetId(String widgetId) throws SQLException String storageBinId; String selectStatement = select storagebinid + from storagebin where widgetid = ? ; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setString(1, widgetId); ResultSet rs = prepStmt.executeQuery(); if (rs.next() storageBinId = rs.getString(1); else storageBinId = null; prepStmt.close(); return storageBinId;客戶端通過調(diào)用findByWidgetId方法(該方法在Home接口中定義,它對應(yīng)與Bean類中的ejbFindByWindgetId方法)來找到物件存放的儲藏箱:String widgetId = 777;StorageBin storageBin = storageBinHome.findByWidgetId(widgetId);String storageBinId = (String)storageBin.getPrimaryKey();int quantity = storageBin.getQuantity();運行StorageBinApp應(yīng)用程序1. 創(chuàng)建storagebin數(shù)據(jù)表a) 進入j2eetutorial/examples目錄b) 執(zhí)行Type ant create-storagebin-table命令2. 部署StorageBinApp.ear文件(在j2eetutorial/examples/ears directory目錄下)3. 運行客戶端a) 進入j2eetutorial/examples/ears目錄b) 將APPCPATH環(huán)境變量設(shè)置為StoreageBinAppClient.jar所在目錄c) 執(zhí)行如下命令(只有一條命令)runclient -client StorageBinApp.ear name StorageBinClient -textauthd) 在登錄提示符下輸入用戶名guest和密碼guest123一對多關(guān)系如果父表的一個主鍵值在子表中匹配多條紀(jì)錄,就是一對多關(guān)系。一對多關(guān)系在數(shù)據(jù)庫應(yīng)用程序中經(jīng)常出現(xiàn)。例如運動社團的應(yīng)用中會有一個team(組)表和一個player(運動員)表。每個組中不會只有一個運動員,但每個運動員只屬于一

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論