kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks
          內(nèi)文:
          前言
          應(yīng)用程式設(shè)計(jì)
          範(fàn)例 3︰一對(duì)一的雙向關(guān)係
          範(fàn)例 4︰多對(duì)多的單向關(guān)係
          範(fàn)例 5︰一對(duì)多的雙向關(guān)係
          參考資料
          關(guān)於作者

          http://www2.tw.ibm.com/developerWorks/tutorial/content/java/t20031013_ejb_part2.html
          這是EJB技術(shù)教學(xué)系列的第 2 部分,這篇技術(shù)教學(xué)旨在向您介紹 Enterprise JavaBeans 2.0(EJB)中,容器管理持久性(Container-Managed Persistence, CMP)和容器管理關(guān)係(Container-Managed Relationships , CMR)。這些特性是 EJB Entity bean 特有的,與一般短暫存在的Session bean 相比較,Entity bean 通常長(zhǎng)時(shí)間存在。

          透過加入以下這些對(duì)Entity bean 的進(jìn)階支援,Enterprise JavaBeans(EJB)2.0 擴(kuò)充了早期的1.1 版本 ︰

          • 更新 Entity bean 的容器管理持久性(container-managed persistence)
          • 對(duì)容器管理關(guān)係(container-managed relationships) 的支援
          • 在配置描述子中定義的用於可移植的 selectfind 方法的 EJB-Query Language(EJB-QL)
          • 加入 local interface 和 local home interface 來最佳化對(duì)同一容器中其它 bean 的存取

          如果您想要購(gòu)買或銷售元件,您很可能希望在您的元件中有一個(gè)持久層(persistence),能夠在應(yīng)用程式伺服器(例如,IBM WebSphere、BEAWebLogic、JBoss/Tomcat 等等)和持久性儲(chǔ)存系統(tǒng)(比如,Oracle、DB2 等等)上跨平臺(tái)工作。您不必在 EJB 中撰寫低階的 JDBC 呼叫來加入這些功能,這就節(jié)省大量時(shí)間並降低複雜程度。一旦您掌握 CMP/CMR,使用這種技術(shù)來撰寫Entity bean 比在 bean-managed persistence(BMP)的 bean 內(nèi)部使用低階 JDBC 進(jìn)行撰寫快。

          本技術(shù)教學(xué)假設(shè)您已經(jīng)閱讀此技術(shù)教學(xué)系列的第一部分(請(qǐng)參閱參考資料)。再次提醒,如果您對(duì) EJB 還不熟悉,或者您需要重新回憶,我建議您閱讀一本 IBM 技術(shù)教學(xué),由 Richard Monson-Haefel 和 Tim Rohaly 合著的 Enterprise JavaBeans Fundamentals。Enterprise JavaBeans Fundamentals 是一篇優(yōu)秀的技術(shù)教學(xué)。

          應(yīng)該關(guān)心 CMP/CMR 嗎?

          容器管理的Entity bean 有什麼用處呢?對(duì)於初學(xué)者,您不必撰寫低階 JDBC 呼叫來儲(chǔ)存 bean 的狀態(tài),而且您不必撰寫程式碼來管理關(guān)係。它都內(nèi)建在 EJB 框架中。關(guān)係的介面直接透過大多數(shù) EJB 工作人員已經(jīng)很熟悉的 java.util.Collectionjava.util.Set 建置。非??岍u

          這個(gè)額外功能包括對(duì)Entity bean 中持久性欄位的 JavaBeans 元件模式的支援。這樣,就不必公開您的類別變數(shù) ─ 這總讓我感到很奇怪 ─ 而是按照我們都知道並喜歡的 JavaBean 技術(shù)標(biāo)準(zhǔn)命名模式來建立 get 和 set 方法。

          我不會(huì)過於強(qiáng)調(diào)這一點(diǎn)。因?yàn)?EJB 2.0 容器將支援大多數(shù)的 SQL 資料庫(kù)(以及其它資料儲(chǔ)存),您可以撰寫使用多種類型資料庫(kù)的元件。這使得銷售要求持久儲(chǔ)存的元件更容易。例如,您可以銷售將在使用 Oracle 的 IT 部門或使用 DB2 的商店發(fā)揮作用的元件。這樣,您不用使用特定於某個(gè)特殊的資料庫(kù)的 SQL 撰寫低階 JDBC 呼叫,而是將使用 EJB-QL 來建立尋找程式和選擇方法,並在配置描述子中描述關(guān)係。

          簡(jiǎn)單地說,CMP/CMR 是跨平臺(tái)元件建立中所缺少的環(huán)節(jié)。CMP/CMR 將刺激企業(yè)級(jí)元件市場(chǎng)的成長(zhǎng)。此外,CMP/CMR 比低階 JDBC 呼叫更容易使用。CMP/CMR 改正很多不足之處,彌補(bǔ) CMR 早期版本中缺少的功能。雖然有很多持久性框架,但是沒有一個(gè)能和 EJB CMP/CMR 一樣,在那麼多的應(yīng)用程式伺服器平臺(tái)上可用。

          對(duì)於本技術(shù)教學(xué)我需要知道什麼?

          本技術(shù)教學(xué)中的範(fàn)例程式碼可於任何支援 EJB 2.0、遵循 J2EE 的應(yīng)用伺服器上執(zhí)行。範(fàn)例程式碼盡可能是規(guī)範(fàn)的;這樣,所有範(fàn)例程式碼就可被佈署到 Java 2 SDK,Enterprise Edition 1.3. 一起提供的 J2EE 參考實(shí)作中。只要您的應(yīng)用程式伺服器支援 EJB 2.0(從而支援 CMP/CMR),那麼只修改 Ant 建置腳本和適當(dāng)?shù)呐渲妹枋鲎?,就能將?fàn)例程式碼佈署到選擇的應(yīng)用程式伺服器。

          儘管您不必是一位專家,但是本技術(shù)教學(xué)假設(shè)您對(duì) Java 很熟悉,並且對(duì) EJB 有一定程度的瞭解。因?yàn)槲覍⒅v述用 XML 撰寫的配置描述子,所以您應(yīng)該具有 XML 的基本知識(shí)。如果您不熟悉 EJB,我建議您閱讀一篇 developerWorks 技術(shù)教學(xué),由 Richard Monson-Haefel 和 Tim Rohaly 所著的 Enterprise JavaBeans Fundamentals(請(qǐng)參閱參考資料)。這是一篇精湛的技術(shù)教學(xué)。即使您不逐字閱讀該技術(shù)教學(xué),我建議您至少將它作為參考。

          雖然就本質(zhì)而言,Ant(一種類似於 make 的基於 XML、開放來源程式碼的建置系統(tǒng))方面的知識(shí)不是先決條件,但是將有助於您理解範(fàn)例中出現(xiàn)的建置腳本。

          您不需要 JDBC 方面的知識(shí),因?yàn)楸炯夹g(shù)教學(xué)中將沒有低階呼叫,但是 SQL 和關(guān)係資料庫(kù)理論的基本知識(shí)是需要的。

          本技術(shù)教學(xué)系列將講述什麼內(nèi)容?

          我沒有撰寫要花費(fèi)幾天時(shí)間來通讀的長(zhǎng)篇大論。我將技術(shù)教學(xué)分為三部分,每部分可以在一小時(shí)左右看完。您可以在一個(gè)午餐休息時(shí)間內(nèi)完成每篇技術(shù)教學(xué)的學(xué)習(xí)。

          EJB 2.0 加入大量的特性和功能,本技術(shù)教學(xué)主要討論 CMP/CMR。這樣,本技術(shù)教學(xué)假設(shè)您具有 EJB 和Entity bean 方面的背景知識(shí)。要理解本技術(shù)教學(xué),您不必是一位 EJB 專家。技術(shù)教學(xué)講述了 local interface、配置描述子 CMP、CMR 欄位和關(guān)係元素。我們還將全面講解關(guān)係類型,如下所示︰

          • 一對(duì)一
          • 一對(duì)多
          • 多對(duì)多

          範(fàn)例中的關(guān)係還包括單向支援和雙向支援。這些關(guān)係在 XML 配置描述子中定義。

          在第 1 部分技術(shù)教學(xué)中,您透過一個(gè)簡(jiǎn)單的 EJB 2.0 風(fēng)格的Entity bean 的範(fàn)例接觸到 CMP/CMR 和 EJB-QL。這個(gè)範(fàn)例的一部分說明在不需要 Java 實(shí)作的情況下,如何使用簡(jiǎn)單的 EJB-QL 來建立尋找程式方法。本技術(shù)教學(xué)正是要讓您適應(yīng)這些術(shù)語和技術(shù),並且增加一個(gè)基本範(fàn)例。

          在本技術(shù)教學(xué),即該系列的第二篇技術(shù)教學(xué)中,您將以第一個(gè)範(fàn)例為基礎(chǔ)來學(xué)習(xí)每種類型的關(guān)係以及每種類型的關(guān)係方向。您將建立一個(gè)客戶端,該客戶端存取您建立的關(guān)係來加入、刪除和變更相關(guān)成員。

           

          應(yīng)用程式設(shè)計(jì)

          應(yīng)用程式設(shè)計(jì)︰Entity 設(shè)計(jì)

          本技術(shù)教學(xué)系列中的範(fàn)例使用一個(gè)用於線上內(nèi)容管理系統(tǒng)的虛構(gòu)認(rèn)證系統(tǒng),它被設(shè)計(jì)為具有以下這些功能︰

          • 將使用者登入到系統(tǒng)
          • 認(rèn)證使用者處?kù)赌撤N角色
          • 容許將使用者組織成群組,從而容許進(jìn)行群組作業(yè)
          • 儲(chǔ)存如位址和連絡(luò)訊息這樣的使用者訊息
          • 管理角色、使用者和 群組(管理 = 加入、編輯、刪除)

          圖 1︰這篇技術(shù)教學(xué)中Entity的概述
          圖 1︰這篇教程中實(shí)體的概述

          圖 1 中系統(tǒng)的Entity的概述說明有四個(gè)截然不同的Entity︰User、Group、Role 以及 UserInfo。這些Entity中的每一個(gè)都有下面這三種關(guān)係︰

          • 多個(gè) User 與多個(gè) Role 相關(guān)聯(lián)(多對(duì)多)
          • 一個(gè) User 有一個(gè) UserInfo(一對(duì)一)
          • 一個(gè) Group 包括多個(gè) User(一對(duì)多)

          第一篇技術(shù)教學(xué)說明怎樣將 CMP 建置到 UserManagement Entity bean 中。在這第二篇技術(shù)教學(xué)中,我將說明怎樣用這些Entity的關(guān)係來實(shí)作每一個(gè)Entity。
           

          範(fàn)例 3︰一對(duì)一的雙向關(guān)係

          關(guān)係

          關(guān)係具有方向︰單向和雙向。並且,關(guān)係有 <multiplicity>︰一對(duì)一、一對(duì)多以及多對(duì)多。

          第一個(gè)範(fàn)例的關(guān)係是雙向的,<multiplicity> 為一對(duì)一。這個(gè)關(guān)係將是 User 與儲(chǔ)存在 UserInfo 中的連絡(luò)訊息之間的關(guān)係。這個(gè)範(fàn)例將完成以下這些工作︰

          1. 定義 UserInfoBean Entity bean。
          2. 將 CMR 欄位新增到 UserBean 中。
          3. 將一個(gè)關(guān)係元素新增到 配置描述子中。
          4. 將程式碼新增到 UserManagement Session bean 中以使用這個(gè)關(guān)係。
          5. 將程式碼新增到客戶端中以使用 UserManagement Session bean 中的新程式碼。

          定義 UserInfoBean

          UserInfoBeanUserBean 一樣,定義 CMP 欄位。CMP 欄位用來儲(chǔ)存描述 UserBean 的連絡(luò)訊息和其它訊息。

          這樣,UserInfoBean 在配置描述子中定義一個(gè)local interface、一個(gè)local home interface、一個(gè)Entity bean 實(shí)作類別以及一個(gè)Entity元素實(shí)體。所有這些程式碼都在清單 1 到清單 4 中。

          清單 1︰UserInfoBean 的 local interface

          /* Local interface */  
          package com.rickhightower.auth;

          import javax.ejb.EJBLocalObject;

          public interface LocalUserInfo extends EJBLocalObject {
              public abstract String getEmail();

              public abstract LocalUser getUser();
              public abstract void setUser(LocalUser user);

              public abstract String getDept();
              public abstract void setDept(String value);

              public abstract String getWorkPhone();
              public abstract void setWorkPhone(String value);

              public abstract String getExtention();
              public abstract void setExtention(String value);

              public abstract boolean getEmployee();
              public abstract void setEmployee(boolean value);

              public abstract String getHomePhone();
              public abstract void setHomePhone(String value);
             
              public abstract String getFirstName();
              public abstract void setFirstName(String value);

              public abstract String getLastName();
              public abstract void setLastName(String value);

              public abstract String getMiddleName();
              public abstract void setMiddleName(String value);
          }
             

          清單 2︰UserInfoBean 的local home interface

          						
          /* Local home interface */			 
          package com.rickhightower.auth;
          
          import javax.ejb.EJBLocalHome;
          import javax.ejb.CreateException;
          import javax.ejb.FinderException;
          
          import java.util.Collection;
          
          public interface LocalUserInfoHome extends EJBLocalHome {
          
              public LocalUserInfo create(
                                  String firstName, String middleName, 
                                  String lastName, String email, 
                                  String dept, String workPhone,
                                  String extention, String homePhone, 
                                  boolean isEmployee)
                                              throws CreateException;
              
              public LocalUserInfo findByPrimaryKey (String email)
          	                                  throws FinderException;
          
          }
          

          包裹 UserInfoBean

          請(qǐng)注意,一個(gè)關(guān)係中所涉及的Entity必須在同一個(gè)配置描述子中定義;這樣,必須在同一個(gè) .jar 文件中包裹這些Entity。UserBeanUserInfoBean 在同一個(gè) EJB .jar 文件中,並且在同一個(gè)配置描述子中定義。

          清單 3︰UserInfoBean 的實(shí)作

          
          /* entity bean implementation class */
          package com.rickhightower.auth;
          
          import javax.ejb.EntityBean;
          import javax.ejb.EntityContext;
          import javax.ejb.CreateException;
          import javax.naming.*;
          
          public abstract class UserInfoBean implements EntityBean {
          
              public String ejbCreate(
                                  String firstName, String middleName,
                                  String lastName, String email, 
                                  String dept, String workPhone,
                                  String extention, String homePhone, 
                                  boolean isEmployee)
                                              throws CreateException {
                  setEmail(email);
                  setDept(dept);
                  setWorkPhone(workPhone);
                  setExtention(extention);
                  setHomePhone(homePhone);
                  setEmployee(isEmployee);
                  setFirstName(firstName);
                  setLastName(lastName);
                  setMiddleName(middleName);
                  return null;
              }
                   
              public void ejbPostCreate(
                                  String firstName, String middleName, 
                                  String lastName, String email, 
                                  String dept, String workPhone, 
                                  String extention, String homePhone, 
                                  boolean isEmployee)
                                            throws CreateException { }
          
              public abstract String getEmail();
              public abstract void setEmail(String value);
          
              public abstract String getFirstName();
              public abstract void setFirstName(String value);
          
              public abstract String getLastName();
              public abstract void setLastName(String value);
          
              public abstract String getMiddleName();
              public abstract void setMiddleName(String value);
          
              public abstract LocalUser getUser();
              public abstract void setUser(LocalUser user);
          
              public abstract String getDept();
              public abstract void setDept(String value);
              
              public abstract String getExtention();
              public abstract void setExtention(String value);
              
              public abstract String getWorkPhone();
              public abstract void setWorkPhone(String value);
          
              public abstract boolean getEmployee();
              public abstract void setEmployee(boolean value);
          
              public abstract String getHomePhone();
              public abstract void setHomePhone(String value);
              
              public void setEntityContext(EntityContext context){ }
              public void unsetEntityContext(){ }
              public void ejbRemove(){ }
              public void ejbLoad(){ }
              public void ejbStore(){ }
              public void ejbPassivate(){ }
              public void ejbActivate(){ }
          }
          	  		  
          

          另請(qǐng)注意下面的程式碼︰

          public abstract LocalUser getUser();
          public abstract void setUser(LocalUser user);

          UserInfoBean 的 local interface 和實(shí)作中都有。這個(gè) setter 和 getter 方法定義這個(gè)雙向關(guān)係的 CMR 欄位。因?yàn)檫@個(gè)關(guān)係是雙向的,所以 UserInfoUserInfoBean 都必須有參照對(duì)方的 CMR 欄位。

          清單 4︰UserInfoBean 的配置描述子


          <entity>
             <display-name>UserInfoBean</display-name>
             <ejb-name>UserInfoBean</ejb-name>

             <local-home>com.rickhightower.auth.LocalUserInfoHome</local-home>
             <local>com.rickhightower.auth.LocalUserInfo</local>
             <ejb-class>com.rickhightower.auth.UserInfoBean</ejb-class>

             <persistence-type>Container</persistence-type>
             <prim-key-class>java.lang.String</prim-key-class>

             <reentrant>True</reentrant>
             <cmp-version>2.x</cmp-version>

             <abstract-schema-name>UserInfoBean</abstract-schema-name>
           
             <cmp-field>
               <field-name>firstName</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>middleName</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>lastName</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>email</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>dept</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>workPhone</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>extention</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>homePhone</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>employee</field-name>
             </cmp-field>

             <cmp-field>
               <field-name>email</field-name>
             </cmp-field>

             <primkey-field>email</primkey-field>
            
          </entity>      

           

          將 CMR 欄位新增到 UserBean

          您需要將 CMR 欄位新增到 UserBean 的 local interface 和 Entity bean 類別中。

          除了 CMR 欄位將分別從 getter 和 setter 方法傳回和傳遞關(guān)係中的另一個(gè)Entity bean 的 local interface 之外,定義 CMR 欄位和定義 CMP 欄位非常相似。在本例中,getter 方法將傳回 LocalUserInfo,如下所示︰

           public abstract LocalUserInfo getUserInfo();
          

          setter 方法將傳遞 LocalUserInfo,如下所示︰

           public abstract void setUserInfo(LocalUserInfo userInfo); 
          

          與 CMP 欄位一樣,實(shí)作這些方法的實(shí)際程式碼由容器實(shí)作來定義。您只需在配置描述子中定義關(guān)係,EJB 容器將提供管理關(guān)係的程式碼。真棒﹗    
           
          package com.rickhightower.auth;

          import javax.ejb.EJBLocalObject;

          public interface LocalUser extends EJBLocalObject {

              public String getEmail();
              public String getPassword();
              public LocalUserInfo getUserInfo();
              public void setUserInfo(LocalUserInfo userInfo);
          }
             
           
          public abstract class UserBean implements EntityBean {

                 
              public abstract LocalUserInfo getUserInfo();
              public abstract void setUserInfo(LocalUserInfo userInfo);
             
             
          }

          在配置描述子中定義關(guān)係

          關(guān)係在 <enterprise-beans> 元素之外定義。當(dāng)您指定關(guān)係時(shí),您必須指定關(guān)係中所涉及的兩個(gè)Entity bean。關(guān)係在 <ejb-relation> 元素中定義。關(guān)係中的每個(gè)角色在 <ejb-relationship-role> 元素中定義。

          清單 5︰Entity bean 的關(guān)係  
           
            <relationships>
              <ejb-relation>
                <ejb-relation-name>UserHasUserInfo</ejb-relation-name>

                <ejb-relationship-role>
                  <ejb-relationship-role-name>
                        UserHasUserInfo
                  </ejb-relationship-role-name>
           
                  <multiplicity>One</multiplicity>
                  <relationship-role-source>
                    <ejb-name>UserBean</ejb-name>
                  </relationship-role-source>
                  <cmr-field>
                    <cmr-field-name>userInfo</cmr-field-name>
                  </cmr-field>
                </ejb-relationship-role>

                <ejb-relationship-role>
                  <ejb-relationship-role-name>
                        UserInfoPartOfUser
                  </ejb-relationship-role-name>
           
                  <multiplicity>One</multiplicity>
                  <cascade-delete />
                  <relationship-role-source>
                    <ejb-name>UserInfoBean</ejb-name>
                  </relationship-role-source>
                  <cmr-field>
                    <cmr-field-name>user</cmr-field-name>
                  </cmr-field>
                </ejb-relationship-role>

              </ejb-relation>
            </relationships>
               

          <ejb-relationship-role> name、multiplicity、source 以及選擇性的 CMR 欄位,分別由下面這些元素定義︰分別是 <ejb-relationship-role-name>、<multiplicity>、帶有 <ejb-name> 子元素的 <relationship-role-source> 以及帶有 <cmr-field-name> 子元素的 <cmr-field>。

           

          在配置描述子中定義關(guān)係

          <ejb-relationship-role-name> 元素可以是您所希望的任何名稱。請(qǐng)儘量使它對(duì)於您所描述的關(guān)係具有描述性。另外,請(qǐng)儘量使它在配置描述子的上下文中是唯一的,如下所示︰
           &nbs葛壑云慟ntity /<ejb-name> 定義的 ejb-bean 名稱。
                 
                  <relationship-role-source>
                    <ejb-name>UserBean</ejb-name>
                  </relationship-role-source>

          <cmr-field>/<cmr-field-name> 必須定義 CMR 欄位名稱。如果 <cmr-field> 由 local interface 中的 <getUserInfo()><setUserInfo()> 定義,那麼它將由 <cmr-field-name> 中的 <userInfo> 定義,如下所示︰
                   
                  <cmr-field>
                    <cmr-field-name>userInfo</cmr-field-name>
                  </cmr-field>
                </ejb-relationship-role>  

          在一個(gè) <ejb-relation> 中總是定義兩個(gè) <ejb-relationship-role>。如果關(guān)係是雙向的,那麼關(guān)係的雙方都將有一個(gè) <cmr-field>。下面是 UserHasUserInfo 關(guān)係中的另一方,如下所示︰

          
                <ejb-relationship-role>
                  <ejb-relationship-role-name>UserInfoPartOfUser</ejb-relationship-role-name>
                  <multiplicity>One</multiplicity>
                  <cascade-delete />
                  <relationship-role-source>
                    <ejb-name>UserInfoBean</ejb-name>
                  </relationship-role-source>
                  <cmr-field>
                    <cmr-field-name>user</cmr-field-name>
                  </cmr-field>
                </ejb-relationship-role>
          	  		  
          

          這裡您可以看到這個(gè)角色的名稱是 UserInfoPartOfUser<ejb-relationship-role-name> 的主體)。您還可以看到Entity bean 是 UserInfoBean<relationship-role-source>/<ejb-name> 的主體)。並且,您可以透過 <cmr-field>/<cmr-field-name> 來識(shí)別出關(guān)係中所包括的 CMR 欄位是 user。

          UserManagement 改為使用關(guān)係

          為了說明怎樣使用 CMR 欄位,UserManagement Session bean 將加入三個(gè)方法︰

          • 使用連絡(luò)訊息的新 addUser()
          • 傳回一個(gè)物件陣列的getUsersInfo() 方法
          • 使用 <userInfo> CMR 欄位的 changeLastName() 方法

          清單 6 和 清單 7 顯示修改過的 UserManagement bean。

          清單 6︰UserManagement 和 UserManagementBean 的介面和實(shí)作  
           
          /** Remote interface */  
          public interface UserManagement extends EJBObject {
               
              public void addUser(String email, String password,
                                  String firstName, String middleName,
                                  String lastName,  String dept,
                                  String workPhone, String extention,
                                  String homePhone, boolean isEmployee   
              ) throws RemoteException;
           
              public UserValue[] getUsersInfo()throws RemoteException;
             
              public void changeLastName(String email, String lastName)
                                              throws RemoteException;
               
           
           
          /** Entity Implementation class */
          public class UserManagementBean implements SessionBean {
               
              public void addUser(String email, String password,
                                  String firstName, String middleName,
                                  String lastName,  String dept,
                                  String workPhone, String extention,
                                  String homePhone, boolean isEmployee){
                  try {
                      LocalUser user = userHome.create(email, password);
                      LocalUserInfo info = infoHome.create(firstName,
                                            middleName, lastName, email, dept,
                                            workPhone, extention, homePhone,
                                            isEmployee);
                      user.setUserInfo(info);
                  } catch (CreateException e) {
                      throw new EJBException
                            ("Unable to create the local user " + email, e);
                  }
                                     
              }
               
              public UserValue[] getUsersInfo(){
                  try{
                      ArrayList userList = new ArrayList(50);
                      Collection collection = userHome.findAll();
                      Iterator iterator = collection.iterator();
                      while(iterator.hasNext()){
                         LocalUser user = (LocalUser)iterator.next();
                         LocalUserInfo info = user.getUserInfo();
                         UserValue userValue = new UserValue(user.getEmail());
                         copyUserInfo(userValue, info);
                         userList.add(userValue);
                      }
              return (UserValue[])
                          userList.toArray(new UserValue[userList.size()]);

                  } catch (FinderException e){
                      throw new EJBException
                                  ("Unable to get list of users ", e);
                  }
              }
               
              public void changeLastName(String email, String lastName){
                  try {
                      LocalUser user = userHome.findByPrimaryKey(email);
                      LocalUserInfo info = user.getUserInfo();
                      info.setLastName(lastName);
                  } catch (FinderException e) {
                      throw new EJBException
                         ("Unable to change the last name " + lastName, e);
                  }
                     
              }
           

          清單 7︰UserManagementBean 的可序列化的 UserValue 類別

          			 
          /** Serializable value class */			
          
          package com.rickhightower.auth;
          
          public class UserValue implements java.io.Serializable{
          
              private String email="";
              private String firstName="";
              private String middleName="";
              private String lastName="";
              private String dept="";
              private String workPhone="";
              private String extention="";
              private String homePhone="";
              private boolean employee;
              
          
              public UserValue() {
              }
              
              public UserValue(String aEmail) {
                 email = aEmail;
              }
              
          
              public String getEmail() { return email;}
              public void setEmail(String email) {this.email=email;}
              
              
              public String getFirstName() {return firstName;}
              public void setFirstName(String firstName){
                 this.firstName=firstName;
              }
          
              public String getMiddleName() {return middleName;}
              public void setMiddleName(String middleName){
                 this.middleName=middleName;
              }
              
              public String getLastName() {return lastName;}
              public void setLastName(String lastName) {
                 this.lastName=lastName;
              }
              
              public String getDept() {return dept;}
              public void setDept(String dept) {
                 this.dept=dept;
              }
              
              public String getWorkPhone() {return workPhone;}
              public void setWorkPhone(String workPhone) {
                 this.workPhone=workPhone;
              }
              
              public String getExtention() {return extention;}
              public void setExtention(String extention) {
                 this.extention=extention;
              }
              
              public String getHomePhone() {return homePhone;}
              public void setHomePhone(String homePhone) {
                 this.homePhone=homePhone;
              }
              
              public boolean isEmployee() {return employee;}
              public void setEmployee(boolean employee) {
                 this.employee = employee;
              }
              
          }
          

          新的 UserManagement 方法

          addUser()

          addUser() 方法說明如何設(shè)定一個(gè) CMR 欄位。

          addUser() 方法將所有的連絡(luò)訊息和使用者訊息作為參數(shù)。
          然後,它使用 UserBeanUserInfoBean 的 home 介面建立 LocalUserLocalUserInfo 實(shí)例,如下所示︰

          			 
          public void addUser(String email, String password, boolean isEmployee){
                          	 
               LocalUser user = userHome.create(email, password);
                 LocalUserInfo info = infoHome.create(firstName, middleName, lastName,
                   email, dept, workPhone, extention, homePhone, isEmployee);
          
          

          一旦 LocalUserLocalUserInfo 物件都建立好了,addUser() 方法就使用新建立的 UserInfo 設(shè)定 User
          <userInfo> CMR 欄位,如下所示︰

          user.setUserInfo(info);
          
          

          getUsersInfo()

          <getUserInfo()> 方法說明如何取得一個(gè) CMR 欄位。
          由於您不能從遠(yuǎn)端方法傳回一個(gè)本地Entity的集合,<getUserInfo()> 說明怎樣傳回帶有物件的一些Entity bean。

          與 getUsers 方法類似,getUsersInfo() 方法使用 UserBean 的 home 介面(LocalUserHome)的 findAll 方法。
          但是,不是傳回每個(gè)使用者的 UserBean 的識(shí)別資料(電子信件),而是傳回每個(gè)使用者的一個(gè)物件,這個(gè)物件包括
          每個(gè)使用者的部門、電子郵件、就業(yè)情況、電話號(hào)碼、last name、middle name first name,如下所示︰

          
          ArrayList userList = new ArrayList(50); 
             Collection collection = userHome.findAll(); 
             Iterator iterator = collection.iterator();
             while(iterator.hasNext()){ 
                  LocalUser user = (LocalUser)iterator.next();
                  LocalUserInfo info = user.getUserInfo(); 
                  UserValue userValue = new UserValue(user.getEmail());
                  copyUserInfo(userValue, info);
                  userList.add(userValue); 
                  } 
                return (UserValue[]) userList.toArray(new UserValue[userList.size()]);                       
          					
          

          對(duì)應(yīng)每個(gè) User/UserInfo 對(duì),UserValue 類別被植入資料。
          UserValue 類別是一個(gè)簡(jiǎn)單的可序列化類別,列在左邊。對(duì)於每個(gè) User/UserInfo 對(duì),
          getUsersInfo() 方法呼叫名為 copyUserInfo() helper method。
          copyUserInfo() 將值從 User/UserInfo 對(duì)複製到UserValue 物件中。下面列出 copyUserInfo() 方法。

          
          private void copyUserInfo(UserValue userValue, LocalUserInfo info){ 
              if (info != null){
             	 userValue.setFirstName(info.getFirstName());
                 	 userValue.setMiddleName(info.getMiddleName());
                 	 userValue.setLastName(info.getLastName());
                    userValue.setDept(info.getDept());
                    userValue.setWorkPhone(info.getWorkPhone());
                    userValue.setExtention(info.getExtention());
                    userValue.setHomePhone(info.getHomePhone());
                    userValue.setEmployee(info.getEmployee()); 
                   } 
            } 
                      
          

          changeLastName()

          changeLastName() 方法說明存取Entity bean 的 CMR 欄位來修改其中一個(gè)相關(guān)物件的 CMR 欄位。

          changeLastName() 方法使用傳給它的電子郵件來尋找 UserBean 的local interface LocalUser,
          然後使用 LocalUser 的 CMR 欄位來獲得對(duì) UserInfoBean 的存取。
          之後,它修改 UserInfoBean 的姓,所有的內(nèi)容如下所示︰

           
          	LocalUser user = userHome.findByPrimaryKey(email);
          	LocalUserInfo info = user.getUserInfo(); 
                   info.setLastName(lastName); 
          
          

          待會(huì)將回顧對(duì)客戶端的變更來練習(xí)這三個(gè)新方法。

           

          將客戶端改為使用新的 UserManagement 方法

          為了使用 UserManagement bean 中定義的新方法,正如前面一樣,您必須修改客戶端。

          請(qǐng)注意,下面的程式碼使用新的 addUser()、changeLastName()getUsersInfo() 方法。

          事實(shí)上,您用 addUsers 建立兩個(gè)使用者。然後變更使用者 Andy last name。並且透過利用 UserManagementBeangetUsersInfo() 方法列印出 lastName,來驗(yàn)證last name變更的結(jié)果。意外的發(fā)現(xiàn)哦﹗
           
            /* Add some user with the new addUser method */
                     userMgmt.addUser("andy@rickhightower.com", "starwars",
                                  "Andy", "Mike", "Barfight",
                                   "Engineering", "555-1212", "x102",
                                  "555-5555", true);
                     userMgmt.addUser("donna@rickhightower.com", "cusslikeasailor",
                                  "Donna", "Marie", "Smith",
                                  "Marketing", "555-1213", "x103",
                                  "555-7777", true);
           
                    
                     System.out.println("Change last name");
                     userMgmt.changeLastName("andy@rickhightower.com", "Smith-Barfight");

                               
                     System.out.println("Get User Info");
                     UserValue [] users = userMgmt.getUsersInfo();

                     for (int index=0; index < users.length; index++){
                      UserValue user = users[index];
                      System.out.println("user firstName =" + user.getFirstName());
                      System.out.println("user lastName =" + user.getLastName());
                      System.out.println("user homePhone =" + user.getHomePhone());
                     }

          編譯和佈署一對(duì)一範(fàn)例

          同樣的技術(shù)也可以用來建置、包裹、佈署和執(zhí)行客戶端。請(qǐng)參考本技術(shù)教學(xué)第一部分的第 8 章,重溫一下怎樣建置和執(zhí)行這個(gè)範(fàn)例應(yīng)用程式。請(qǐng)檢視 cmpCmr/section3 下的程式碼和建置文件。

          請(qǐng)務(wù)必執(zhí)行 ant clean 來刪除舊範(fàn)例的文件。

          您已經(jīng)完成最前面的三個(gè)範(fàn)例。如果您對(duì)此已經(jīng)理解透徹,就可以向終點(diǎn)線衝刺了。下一章將講述多對(duì)多關(guān)係。

           

          範(fàn)例 4︰多對(duì)多的單向關(guān)係

          多對(duì)多關(guān)係

          多對(duì)多關(guān)係聽起來極其難以實(shí)作。實(shí)際上,它和一對(duì)一關(guān)係一樣容易實(shí)作。EJB 容器替您做了所有最難做的工作。

          對(duì)於這個(gè)範(fàn)例,您將新增使用者可能處?kù)兜牟煌巧?。單個(gè)使用者可能處?kù)抖鄠€(gè)角色。並且一個(gè)角色可以與多個(gè)使用者相關(guān)聯(lián)。

          在這個(gè)範(fàn)例中,您將做下面這些事︰

          1. 定義 RoleBean
          2. 在配置描述子中定義從 UserBeanRoleBean 的關(guān)係。
          3. 將一個(gè) CMR 集合欄位新增到 UserBean 中。
          4. 將程式碼新增到 UserManagement Session bean 中以使用這種關(guān)係。
          5. 將程式碼新增到客戶端以使用 UserManagement Session bean 中的新程式碼。

          定義 RoleBean

          RoleBean 與上一範(fàn)例中的 UserInfoBean 類似。和所有其它Entity bean 一樣,它有 CMP 欄位。它還有一個(gè)本地 home、一個(gè)local interface和一個(gè)Entity bean 實(shí)作。

          與上一個(gè)範(fàn)例中的 UserInfoBean 不同,RoleBean 沒有 <cmr-field>。下面列出 RoleBean 完整的清單。

          清單 8︰RoleBean local interface

          
          package com.rickhightower.auth; 
          import javax.ejb.EJBLocalObject; 
          
          public interface LocalRole extends EJBLocalObject {
              public abstract String getName(); 
              public abstract String getDescription(); 
          }
                                   
          

          清單 9︰RoleBean Home interface

          
          package com.rickhightower.auth; 
          import javax.ejb.EJBLocalHome; 
          import javax.ejb.CreateException; 
          import javax.ejb.FinderException; 
          import java.util.Collection; 
          
          public interface LocalRoleHome extends EJBLocalHome { 
              public LocalRole create (String name, String description) throws CreateException; 
              public LocalRole findByPrimaryKey (String email) throws FinderException; 
              public Collection findAll() throws FinderException; 
          } 
                                   
          

          清單 10︰RoleBean Entity bean 實(shí)作類別

          
          package com.rickhightower.auth; 
          import javax.ejb.EntityBean; 
          import javax.ejb.EntityContext; 
          import javax.ejb.CreateException; 
          import javax.naming.*; 
          
          public abstract class RoleBean implements EntityBean { 
          
              public String ejbCreate(String name, String description) throws CreateException { 
                  setName(name);
                  setDescription(description); 
                  return null; 
              } public 
          
              void ejbPostCreate(String name, String description) throws CreateException{ } 
          
              public abstract String getName(); 
              public abstract void setName(String name); 
          
              public abstract String getDescription(); 
              public abstract void setDescription(String description);
          
              public void setEntityContext(EntityContext context){ } 
              public void unsetEntityContext(){ } 
              public void ejbRemove(){ } 
              public void ejbLoad(){ }
              public void ejbStore(){ } 
              public void ejbPassivate(){ } 
              public void ejbActivate(){ } 
          } 
                                    
          

          清單 11︰RoleBean 配置描述子

          
              <entity>
                <display-name>RoleBean</display-name>
                <ejb-name>RoleBean</ejb-name>
          
                <local-home>com.rickhightower.auth.LocalRoleHome</local-home>
                <local>com.rickhightower.auth.LocalRole</local>
                <ejb-class>com.rickhightower.auth.RoleBean</ejb-class>
          
                <persistence-type>Container</persistence-type>
                <prim-key-class>java.lang.String</prim-key-class>
          
                <reentrant>False</reentrant>
                <cmp-version>2.x</cmp-version>
          
                <abstract-schema-name>RoleBean</abstract-schema-name>
          
                <cmp-field>
                  <description>no description</description>
                  <field-name>name</field-name>
                </cmp-field>
                <cmp-field>
                  <description>no description</description>
                  <field-name>description</field-name>
                </cmp-field>
                <primkey-field>name</primkey-field>
                <security-identity>
                  <description></description>
                  <use-caller-identity></use-caller-identity>
                </security-identity>
          
                <query>
                  <description></description>
                  <query-method>
                    <method-name>findAll</method-name>
                    <method-params />
                  </query-method>
                  <ejb-ql>select Object(o) from RoleBean </ejb-ql>
                </query>
          
              </entity>
          
            </enterprise-beans>
          

          在配置描述子中定義關(guān)係

          加入多對(duì)多關(guān)係的 XML 元素和技術(shù)與加入一對(duì)一關(guān)係的 XML 元素和技術(shù)基本相同。唯一的關(guān)鍵的不同之處是 multiplicityRoleBean<ejb-relationship-role> 沒有 CMR 欄位元素,因?yàn)閺?UserBeanRoleBean 的關(guān)係是單向的。RoleBean 不知道 UserBean。下面列出了 <ejb-relation> 元素︰

          
          

          請(qǐng)注意,UserBeanToRoleBean<multiplicity> 為 Many,而且 UserBeanToRoleBean<cmr-field> 有一個(gè)子元素 <cmr-field-type><cmr-field-type> 元素用值為 Many 的 <multiplicity> 的關(guān)係定義 Java 程式碼類型。請(qǐng)注意,兩種可能是 java.util.Collectionjava.util.Set。因?yàn)槟x擇 java.util.Collection 以及 CMR 欄位名稱是 roles,那麼您可以猜到會(huì)在傳回和設(shè)定 java.util.CollectionUserBean 的 local interface 中看到一個(gè)叫做 roles 的 CMR 欄位(setter 和 getter 方法組)。

           

          將集合 CMR 欄位新增到 UserBean

          CMR 欄位傳回並設(shè)定很多角色。因此與 UserInfo 的一對(duì)一關(guān)係的 CMR 欄位不同,您將設(shè)定並取得角色的集合,如下所示︰

          清單 12︰UserBean Entity bean 實(shí)作類別

          		  
          public abstract class UserBean implements EntityBean {
                       
              public abstract Collection getRoles();
              public abstract void setRoles(Collection roles);
              	 
          }
          		   

          清單 13︰UserBean local interface

          
          package com.rickhightower.auth; 
          import javax.ejb.EJBLocalObject; 
          import java.util.Collection; 
          
          public interface LocalUser extends EJBLocalObject { 
          
              public Collection getRoles(); 
              public void setRoles(Collection roles); 
          
              public String getEmail(); 
              public String getPassword(); 
              public LocalUserInfo getUserInfo(); 
              public void setUserInfo(LocalUserInfo userInfo); 
          } 
                             
          

          就是這樣。它與一對(duì)一關(guān)係沒有太大區(qū)別。接下來,我將講解使用多對(duì)多關(guān)係的 UserManagement Session bean 中的方法。

          UserManagement bean 中使用多對(duì)多關(guān)係

          UserManagementBean 加入四個(gè)方法來作用 Role 以及 User 和角色之間的關(guān)係,如下所示︰inRole()、addRole()createRole()removeRole()。

          createRole()removeRole() 方法只不過是將角色新增到資料儲(chǔ)存以及從資料儲(chǔ)存刪除角色的範(fàn)本化程式碼 ─ 沒有什麼新內(nèi)容。

          addRole()

          addRole() 將一個(gè)角色新增到 UserBean 中,如下所示︰

          
          public void addRole(String email, String roleName){ 
              
              LocalUser user = userHome.findByPrimaryKey(email); 
              LocalRole role = roleHome.findByPrimaryKey(roleName); 
              Collection roles = user.getRoles();
              roles.add(role); 
               
          }                          
          

          請(qǐng)注意,addRole()roleHome 檢視角色,然後它將角色從 CMR 角色欄位新增到集合中。這樣,當(dāng)角色被新增到角色集合中時(shí),EJB 容器更新資料儲(chǔ)存。因此,將關(guān)係插入到資料儲(chǔ)存的程式碼是 Collection 類別的介面。酷﹗

          inRole()

          inRole() 方法檢查使用者是否處?kù)赌硞€(gè)角色︰

          public boolean inRole(String email, String roleName){
              
              LocalUser user = userHome.findByPrimaryKey(email);
              Collection roles = user.getRoles();
              Iterator iter = roles.iterator();
              while (iter.hasNext()){
                  LocalRole role = (LocalRole)iter.next();
                  if (role.getName().equals(roleName)) return true;
              }
              
              return false;
          }
                          

          因?yàn)橘Y料儲(chǔ)存的 API 與 java.util.Collection 相同,用 CMR 編碼既容易又快速。

          使用 UserManagementinRole()addRole() 方法

          客戶端使用所有新的 UserManagement 方法,如下所示︰


              //Create Roles -- section 4
              userMgmt.createRole("admin", "Adminstrator");
              userMgmt.createRole("manager", "Content Manager");
              userMgmt.createRole("user", "Normal User");
              userMgmt.createRole("guest", "Guest User");
             
              //Add roles to user Andy -- section 4
              userMgmt.addRole("andy@rickhightower.com", "admin");
              userMgmt.addRole("andy@rickhightower.com", "user");

              //See if Andy is in role admin -- section 4
              if (userMgmt.inRole("andy@rickhightower.com","admin")){
                  System.out.println("Andy is an admin");
              }

              //See if Andy is in role manager -- section 4
              if (!userMgmt.inRole("andy@rickhightower.com","manager")){
                  System.out.println("Andy is not a manager");
              }

              /* Remove Roles -- section 4 */
              userMgmt.removeRole("admin");
              userMgmt.removeRole("manager");
              userMgmt.removeRole("user");
              userMgmt.removeRole("guest");


          編譯和佈署多對(duì)多範(fàn)例

          同樣的技術(shù)也可以用來建置、包裹、佈署和執(zhí)行客戶端。請(qǐng)參閱本技術(shù)教學(xué)第一部分的第 8 章,重溫一下怎樣建置和執(zhí)行這個(gè)範(fàn)例應(yīng)用程式。請(qǐng)檢視 cmpCmr/section4 下的程式碼和建置文件。

          請(qǐng)務(wù)必執(zhí)行 ant clean 來刪除舊範(fàn)例的文件。

          您已經(jīng)完成最前面的四個(gè)範(fàn)例。如果您對(duì)此已經(jīng)理解透徹,所有的內(nèi)容都可以迎刃而解,您就可以順風(fēng)而行。下一章將講述一對(duì)多關(guān)係。

           

          範(fàn)例 5︰一對(duì)多的雙向關(guān)係

          一對(duì)多關(guān)係

          一對(duì)多關(guān)係和其它關(guān)係非常相似。和前面一樣,EJB 容器完成最艱巨的工作。

          在這個(gè)範(fàn)例中,您將做下面這些事︰

          1. 定義 GroupBean
          2. 在配置描述子中定義從 UserBeanGroupBean 的雙向關(guān)係。
          3. 將一個(gè) CMR 集合欄位新增到 UserBean 中。
          4. 將程式碼新增到 UserManagement Session bean 中以使用這個(gè)關(guān)係。
          5. 將程式碼新增到客戶端中以使用 UserManagement Session bean 中的新程式碼。

          定義 GroupBean

          GroupBean 類似於前兩個(gè)範(fàn)例中的 UserInfoBeanRoleBean。和所有其它的Entity bean 一樣,它有 CMP 欄位。它還有本地 home、local interface和Entity bean 實(shí)作。

          和第一個(gè)關(guān)係範(fàn)例中的 UserInfoBean 一樣,GroupBean 有一個(gè)參照 UserBean<cmr-field>。和 UserInfoBean 不同,GroupBean 中的 <cmr-field> 的使用者是 UserBean 的集合。下面列出 GroupBean 完整的清單︰

          清單 14︰GroupBean local interface

          package com.rickhightower.auth;
          import javax.ejb.EJBLocalObject;
          import java.util.Collection;
          
          public interface LocalGroup extends EJBLocalObject { 
          
              public abstract Collection getUsers(); 
              public abstract void setUsers(Collection collection);
          
              public abstract String getName();
              public abstract String getDescription(); 
          }
          				
          

          清單 15︰GroupBean Home interface

          package com.rickhightower.auth;
           
          import javax.ejb.EJBLocalHome; 
          import javax.ejb.CreateException; 
          import javax.ejb.FinderException; 
          import java.util.Collection; 
          
          public interface LocalGroupHome extends EJBLocalHome { 
              public LocalGroup create (String name, String description) throws CreateException; 
              public LocalGroup findByPrimaryKey (String name) throws FinderException; 
          
              public Collection findAll() throws FinderException; 
          } 
          
          

          清單 16︰GroupBean Entity bean 實(shí)作類別

          package com.rickhightower.auth; 
          
          import javax.ejb.EntityBean; 
          import javax.ejb.EntityContext; 
          import javax.ejb.CreateException; 
          import java.util.Collection; 
          import javax.naming.*;
          
          public abstract class GroupBean implements EntityBean { 
          
              public String ejbCreate(String name, String description) throws CreateException {
                  setName(name); 
                  setDescription(description); 
                  return null; 
              } 
          
              public void ejbPostCreate(String name, String description) throws CreateException{ } 
          
              public abstract Collection getUsers(); 
              public abstract void setUsers(Collection collection); 
          
              public abstract String getName(); 
              public abstract void setName(String name); 
          
              public abstract String getDescription(); 
              public abstract void setDescription(String description); 
          
              public void setEntityContext(EntityContext context){ } 
              public void unsetEntityContext(){ }
              public void ejbRemove(){ } 
              public void ejbLoad(){ } 
              public void ejbStore(){ }
              public void ejbPassivate(){ } 
              public void ejbActivate(){ } 
          } 
          
          

          清單 17︰GroupBean 配置描述子項(xiàng)目

          
              <entity>
                <display-name>GroupBean</display-name>
                <ejb-name>GroupBean</ejb-name>
          
                <local-home>com.rickhightower.auth.LocalGroupHome</local-home>
                <local>com.rickhightower.auth.LocalGroup</local>
                <ejb-class>com.rickhightower.auth.GroupBean</ejb-class>
          
                <persistence-type>Container</persistence-type>
                <prim-key-class>java.lang.String</prim-key-class>
          
                <reentrant>False</reentrant>
                <cmp-version>2.x</cmp-version>
          
                <abstract-schema-name>GroupBean</abstract-schema-name>
          
                <cmp-field>
                  <description>The group name</description>
                  <field-name>name</field-name>
                </cmp-field>
                <cmp-field>
                  <description>The description of the group</description>
                  <field-name>description</field-name>
                </cmp-field>
          
                <primkey-field>name</primkey-field>
          
                <security-identity>
                  <description></description>
                  <use-caller-identity></use-caller-identity>
                </security-identity>
          
                <query>
                  <description></description>
                  <query-method>
                    <method-name>findAll</method-name>
                    <method-params />
                  </query-method>
                  <ejb-ql>select Object(group) from GroupBean group</ejb-ql>
                </query>
          
              </entity>
          

          在配置描述子中定義關(guān)係

          用來加入一對(duì)多關(guān)係的 xml 元素和技術(shù)與加入一對(duì)一和多對(duì)多關(guān)係的 xml 元素和技術(shù)幾乎相同。唯一的關(guān)鍵的不同之處是 multiplicity。GroupBean<ejb-relationship-role> 有一個(gè) CMR 欄位元素,因?yàn)閺?UserBeanGroupBean 的關(guān)係是雙向的。GroupBean 有一個(gè)名為 users 的 CMR 欄位。UserBean 有一個(gè)名為 group 的 CMR 欄位。下面列出了 <ejb-relation> 元素︰

          
              <ejb-relation>
          
                <ejb-relation-name>GroupsHaveUsers</ejb-relation-name>
          
                <ejb-relationship-role>
                  <ejb-relationship-role-name>GroupHasUsers</ejb-relationship-role-name>
                  <multiplicity>One</multiplicity>
          
                  <relationship-role-source>
                    <ejb-name>GroupBean</ejb-name>
                  </relationship-role-source>
          
                  <cmr-field>
                    <cmr-field-name>users</cmr-field-name>
                    <cmr-field-type>java.util.Collection</cmr-field-type>
                  </cmr-field>
          
                </ejb-relationship-role>
          
                <ejb-relationship-role>
          
                  <ejb-relationship-role-name>UsersInGroup</ejb-relationship-role-name>
                  <multiplicity>Many</multiplicity>
          
                  <relationship-role-source>
                    <ejb-name>UserBean</ejb-name>
                  </relationship-role-source>
          
                  <cmr-field>
                    <cmr-field-name>group</cmr-field-name>
                  </cmr-field>
          
                </ejb-relationship-role>
          
              </ejb-relation>
          			 
          			 
          

          請(qǐng)注意,GroupHasUsers 的 multiplicity 為 One,因?yàn)樵谶@個(gè)關(guān)係中有一個(gè)群組,並且和上一個(gè)範(fàn)例 GroupHasUsers<cmr-field> 一樣,有一個(gè)子元素 <cmr-field-type>,如下所示︰

          
                  <cmr-field>
                    <cmr-field-name>users</cmr-field-name>
                    <cmr-field-type>java.util.Collection</cmr-field-type>
                  </cmr-field>
          

          欄位關(guān)係的類型是 java.util.Collection,CMR 欄位名稱是 users。

          關(guān)係的另一方 UsersInGroup 的 <multiplicity> 為 Many,因?yàn)檫@個(gè)群組裡有很多使用者。另請(qǐng)注意將 <cmr-field> 設(shè)定為 group。

           

          將 CMR 欄位群組新增到 UserBean

          CMR 欄位 group 容許您將這個(gè)使用者設(shè)定到一個(gè)群組中或者取得使用者所在的群組。這樣,和 UserInfo 的一對(duì)一關(guān)係的 CMR 欄位一樣,您可以設(shè)定並取得與群組相關(guān)聯(lián)的集合︰

          清單 18︰UserBean Entity bean 實(shí)作類別
           
          public abstract class UserBean implements EntityBean {
                      
              public abstract LocalGroup getGroup();
              public abstract void setGroup(LocalGroup group);
               
          }

          清單 19︰UserBean local interface

          package com.rickhightower.auth; 
          
          import javax.ejb.EJBLocalObject; 
          import java.util.Collection; 
          
          public interface LocalUser extends EJBLocalObject { 
          
              public LocalGroup getGroup(); 
              public void setGroup(LocalGroup group); 
          
              public Collection getRoles(); 
              public void setRoles(Collection roles); 
          
              public String getEmail(); 
              public String getPassword(); 
              public LocalUserInfo getUserInfo(); 
              public void setUserInfo(LocalUserInfo userInfo); 
          } 
          
          

          它和其它關(guān)係範(fàn)例沒有太大區(qū)別。接下來我將講解使用多對(duì)多關(guān)係的 UserManagement Session bean 中的方法。

          UserManagement 中使用一對(duì)多關(guān)係

          UserManagementBean 加入四個(gè)方法,每個(gè)方法都作業(yè) Groups 以及 UserGroups 之間的關(guān)係,如下所示︰inGroup()moveUserToGroup()、addRoleToUsers()getUsersInGroup()createGroup()removeGroup()、getGroups()getRoles()。

          createGroup()removeGroup() 方法都只是將群組新增到資料儲(chǔ)存中以及從資料儲(chǔ)存刪除群組的範(fàn)本化程式碼 ─ 又是沒有什麼新內(nèi)容。加入方法 getRoles()getGroups() 來顯示可用的角色和群組 。

          inGroup()

          inGroup() 方法檢查一個(gè)使用者是否在某個(gè)群組中︰

          public boolean inGroup(String email, String groupName){ 
               
              LocalUser user = userHome.findByPrimaryKey(email); 
              return user.getGroup().getName().equals(groupName); 
               
          }
          
          moveUserToGroup() 

          moveUserToGroup() 將使用者移到另一個(gè)群組中︰

          public void moveUserToGroup(String email, String groupName){ 
              
              LocalUser user = userHome.findByPrimaryKey(email); 
              LocalGroup group = groupHome.findByPrimaryKey(groupName);
          				
              user.setGroup(group);
          
              /* The relationship works both way so this would work too! */ 
          
              //<emph>group.getUsers().add(user);
               
          
          

          addRoleToUsers()

          addRoleToUsers() 使用群組到使用者和角色到使用者的兩種關(guān)係。它將 Role 新增到一個(gè)群組裡的每個(gè)使用者中。

          public void addRoleToUsers(String groupName, String roleName){ 
               
              LocalGroup group = groupHome.findByPrimaryKey(groupName);
              LocalRole role = roleHome.findByPrimaryKey(roleName); 
              Collection users = group.getUsers(); 
              Iterator iterator = users.iterator();
          
              while(iterator.hasNext()){ 
                  LocalUser user = (LocalUser)iterator.next();
                  user.getRoles().add(role); 
              }     
          }
          

          getUsersInGroup()

          getUsersInGroup() 使用使用者到 <userInfo> 的關(guān)係以及使用者到群組的關(guān)係,傳回一個(gè)字串陣列,每個(gè)字串包括群組中每個(gè)使用者的名、姓和電子郵件。

          public String[] getUsersInGroup(String groupName){ 
              LocalGroup group = groupHome.findByPrimaryKey(groupName); 
              Collection users = group.getUsers(); 
              Iterator iterator = users.iterator(); 
              ArrayList userList = new ArrayList (50); 
              while(iterator.hasNext()){ 
                  LocalUser user = (LocalUser)iterator.next(); 
          
                  String firstName = user.getUserInfo().getFirstName(); 
                  String lastName = user.getUserInfo().getLastName(); 
                  String email = user.getEmail(); 
          
                  StringBuffer sUser = new StringBuffer(80); 
                  sUser.append(firstName + ", ");
                  sUser.append(lastName + ", "); 
                  sUser.append(email);
                  userList.add(sUser.toString()); 
              } 
              return (String []) userList.toArray(new String[userList.size()]); 
               
          }

          現(xiàn)在,我們來修改客戶端,以便可以使用這種程式碼。

          使用 UserManagementinGroup()、moveUserToGroup()、addRoleToUsers()getUsersInGroup() 方法

          客戶端使用所有新的 UserManagement 的方法,如下所示︰

          System.out.println("Create and Display groups");
          userMgmt.createGroup("marketing", "Marketing group");
          userMgmt.createGroup("engineering", "Engineering group");
          userMgmt.createGroup("sales", "Sales group"); 
          userMgmt.createGroup("IT","Information Technology group"); 
          
              /** Display the created groups */ 
          String [] groups = userMgmt.getGroups(); 
          
          for (int index=0; index < groups.length; index++){ 
              System.out.println(groups[index]); 
          } 
          
          createUsers(userMgmt); //updated for section 3 
          
              /** Section 5 Add role to users */ 
          String group = "engineering"; 
          String role = "super_user"; 
          userMgmt.addRoleToUsers(group,role);
          
          group = "IT"; 
          role = "admin"; 
          userMgmt.addRoleToUsers(group,role); 
          
          group = "marketing"; 
          role = "user"; 
          userMgmt.addRoleToUsers(group,role); 
          
          
              /** Section 5 -- list users in group engineering */ 
          String [] users = userMgmt.getUsersInGroup("engineering"); 
          System.out.println("Users in the engineering group"); 
          
          for (int index=0; index < users.length; index++){
               System.out.println(users[index]); 
          } 
          
              /** Section 5 -- Is Andy in group Engineering ? */ 
          
          if (userMgmt.inGroup("andy@rickhightower.com","engineering")){
              System.out.println("Andy is in the engineering group"); 
          } 
          
              /** Section 5 -- 
                Is Andy in group the super_user role that was assigned 
                to all users in engineering? */ 
          if (userMgmt.inRole("andy@rickhightower.com","super_user")){
              System.out.println("Andy is a super_user"); 
          } 
          
          /** Section 5 -- Move Andy to marketing */ 
          userMgmt.moveUserToGroup("andy@rickhightower.com", "marketing");
          
          /** Section 5 -- Is Andy in group Engineering ? */ 
          if (userMgmt.inGroup("andy@rickhightower.com","engineering")){
              System.out.println("Andy is in the engineering group"); 
          } else if(userMgmt.inGroup("andy@rickhightower.com","marketing")){
              System.out.println("Andy is now in the marketing group"); 
          }
          
          /**Section 5 **/ 
          userMgmt.removeGroup("marketing"); 
          userMgmt.removeGroup("engineering");
          userMgmt.removeGroup("sales"); 
          userMgmt.removeGroup("IT"); 
          

          編譯和佈署一對(duì)多範(fàn)例

          同樣的技術(shù)也可以用來建置、包裹、佈署和執(zhí)行客戶端。請(qǐng)參閱本技術(shù)教學(xué)第一部分的第 8 章,重溫一下怎樣建置和執(zhí)行這個(gè)範(fàn)例應(yīng)用程式。請(qǐng)檢視 cmpCmr/section5 下的程式碼和建置文件。

          請(qǐng)務(wù)必執(zhí)行 ant clean 來刪除舊範(fàn)例的文件。

           

          結(jié)論

          現(xiàn)在,您已經(jīng)完成本技術(shù)教學(xué)系列最前面的五個(gè)範(fàn)例以及兩篇技術(shù)教學(xué)的學(xué)習(xí)??雌饋砟呀?jīng)達(dá)到預(yù)定目標(biāo)了。

          您已經(jīng)建立一對(duì)一、一對(duì)多以及多對(duì)多關(guān)係。您使用集合將Entity新增到其它Entity中,而 EJB 容器將行新增到底層的連線表和欄位中。

          總結(jié)一下,您可以用 deploytool 檢視 Entity .jar 文件中的關(guān)係,如圖 2 和圖 3 所示。

          圖 2︰本技術(shù)教學(xué)中您建立的所有關(guān)係
          圖 2︰本教程中您建立的所有關(guān)係

          圖 3︰Group 的 CMR 和 CMP 欄位
          圖 3︰Group 的 CMR 和 CMP 欄位

          在本技術(shù)教學(xué)系列的第三篇,即最後一部分技術(shù)教學(xué)中,我將說明 EJB-QL 的功能。

          參考資料

          參考書籍

          作者

          Rick Hightower,eBlox 的開發(fā)主管,具有十多年的軟體工作人員經(jīng)驗(yàn)。他領(lǐng)導(dǎo)採(cǎi)用新過程(比如,極端編碼)和新技術(shù)(比如 CMP 和 CMR)。

          Rick 的出版品包括 Java Tools for eXtreme Programming,它講述了佈署和測(cè)試 J2EE 工程(由 John Wiley 出版);他參與合著的 Java Developer's Journal(由 Sams 出版),還有 Java Developer's Journal 中發(fā)表過幾篇的文章。

           

          posted on 2005-03-30 15:25 笨笨 閱讀(1060) 評(píng)論(0)  編輯  收藏 所屬分類: J2EE 、ALL
          主站蜘蛛池模板: 纳雍县| 嘉荫县| 沙田区| 建平县| 绥江县| 通化县| 布拖县| 且末县| 宁海县| 青海省| 民乐县| 闽侯县| 许昌市| 莱州市| 长宁区| 沁水县| 泽库县| 竹溪县| 壶关县| 浦北县| 上林县| 清水河县| 格尔木市| 长岛县| 工布江达县| 迭部县| 乡宁县| 金塔县| 阿克陶县| 长岛县| 来凤县| 平罗县| 崇文区| 上虞市| 建湖县| 通城县| 峡江县| 高邮市| 凤台县| 乡宁县| 那曲县|