同一個目標,同一個夢想

          One Target,One Dream
          posts - 25, comments - 11, trackbacks - 0, articles - 37

          實體Bean的BMP和CMP選擇

          Posted on 2008-11-10 09:40 J2EE Home工作室 閱讀(153) 評論(0)  編輯  收藏 所屬分類: EJB

          EJB有兩種主要類型BMP(Bean managed persistence )和CMP(Container managed persistence ),這兩種類型各有優缺點。

          BMP是在Bean中完成對數據庫JDBC的各種調用,也就是說,在你的實體bean(entity bean)中,明確寫入了SQL語句,如"insert .. "或"select ..",并且使用Datasource獲得一個數據庫資源以及連接(connection)從而對數據庫直接進行增加 刪除修改。

          CMP是由EJB容器自動完成對數據庫的操作,你所有做的,就是在實體bean重寫入SetXXX或getXXX方法,然后在ejb-jar.xml中定義cmp-field就可以。

          很明顯,CMP編寫要簡單多,而且數據庫操作由EJB容器完成應該是一種趨勢,但是CMP有個缺點就是不夠靈活,如果我們要完成類似SQL搜索語句的like命令,如"select * from A where name like '%banqiao'",CMP就無法自動幫助我們完成,這樣我們就需要BMP自己來寫。

          在實際應用,一般為了效率考慮,我們盡量使用CMP,但如何為將來有可能使用BMP作好準備,就是說有可以延伸到BMP的基礎。EJB 2.0對CMP的抽象類支持為我們提供了這種實現的基礎。

          總體思路是,先使用抽象類完成CMP 如果需要BMP 可以extend這個抽象類,然后覆蓋原來的方法(用自己的特殊SQL語句操作來覆蓋該方法)。

          以Java 寵物店(Java Pet Store Demo 1.3)中的地址實體bean:AddressEJB為例:

          public abstract class AddressEJB implements EntityBean {

          private EntityContext context = null;

          // getters and setters for PO CMP fields

          public abstract String getFirstName();
          public abstract void setFirstName(String name);
          public abstract String getLastName();
          public abstract void setLastName(String name);
          public abstract String getStreet1();
          public abstract void setStreet1(String name);
          public abstract String getStreet2();
          public abstract void setStreet2(String name);
          public abstract String getCity();
          public abstract void setCity(String name);
          public abstract String getState();
          public abstract void setState(String name);
          public abstract String getCountry();
          public abstract void setCountry(String name);
          public abstract String getZip();
          public abstract void setZip(String name);

          public Object ejbCreate(String fName, String lName, String s1,
          String s2, String cy, String st,
          String cnty, String pcode)
          throws CreateException {
          setFirstName(fName);
          setLastName(lName);
          setStreet1(s1);
          setStreet2(s2);
          setCity(cy);
          setState(st);
          setCountry(cnty);
          setZip(pcode);
          return null;
          }

          public void ejbPostCreate(String fName, String lName, String street1,
          String street2, String city, String state,
          String country, String zip)
          throws CreateException{}
          public void setEntityContext(EntityContext c){ context = c; }
          public void unsetEntityContext(){}
          public void ejbRemove() throws RemoveException {}
          public void ejbActivate() {}
          public void ejbPassivate() {}
          public void ejbStore() {}
          public void ejbLoad() {}
          }

          在上面的AddressEJB中,我們看到只有setXXX或getXXX的方法。

          在相應的部署描述文件ejb-jar.xml中我們看到:

          <entity>
            <display-name>AddressEJB</display-name>
            <ejb-name>AddressEJB</ejb-name>
            <local-home>com.sun.j2ee.blueprints.address.ejb.AddressLocalHome</local-home>
            <local>com.sun.j2ee.blueprints.address.ejb.AddressLocal</local>
            <ejb-class>com.sun.j2ee.blueprints.address.ejb.AddressEJB</ejb-class>
            <persistence-type>Container</persistence-type>
            <prim-key-class>java.lang.Object</prim-key-class>
            <reentrant>False</reentrant>
            <cmp-version>2.x</cmp-version>
            <abstract-schema-name>Address</abstract-schema-name>

            <cmp-field>
              <field-name>firstName</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>lastName</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>street1</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>street2</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>city</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>state</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>country</field-name>
            </cmp-field>
            <cmp-field>
              <field-name>zip</field-name>
            </cmp-field>


            <security-identity>
              <description></description>
              <use-caller-identity></use-caller-identity>
            </security-identity>

          </entity>

          在上面部署文件中,標明了Address數據庫字段:

          firstName,lastName,street1,street2,city,state,country,zip

          一旦我們要使用BMP, 只要繼承上面的CMP bean:

          public class AddressBeanBMP extends AddressEJB {

          用我們自己的BMP方法覆蓋AddressEJB中的方法:

          ejbLoad() -->從數據庫中獲取數據(SELECT)
          ejbStore() -->修改數據庫數據UPDATE)
          ejbRemove() -->刪除數據庫數據(DELETE)
          ejbCreate() -->插入新的數據記錄(INSERT)
          ejbFindByPrimaryKey(primary key) --> 確保 primary key 存在.
          ejbFindAllPrimaryKey() -->自己的定義 返回一個primary key所有數據記錄的collectionxiam

          下面以ejbCreate()為例:

          public Object ejbCreate(String fName, String lName, String s1,
          String s2, String cy, String st,
          String cnty, String pcode) throws CreateException {

          // insert row into database
          this.fName = fName;
          this.lName = lName;
          this.s1 = s1;
          this.s2 = s2;
          this.cy=cy;
          this.st=st;
          this.cnty=cnty;
          this.pcode=pcode;

          // Insert database record
          try {
          Connection connection = getConnection();
          PreparedStatement statement = connection.prepareStatement
          ("INSERT INTO Address (firstName,lastName,street1,street2,city,state,country,zip) VALUES (?, ?, ?,?,?,?)");
          statement.setString(1, fName);
          statement.setString(2, lName);
          statement.setString(3, pcode);
          statement.setString(4, s1);
          statement.setString(5, s2);
          statement.setString(6, st);
          statement.setString(7, cy);
          statement.setString(8, cnty);
          if (statement.executeUpdate() != 1) {
          statement.close();
          connection.close();
          throw new CreateException("Could not create: " );
          }
          statement.close();
          connection.close();
          }
          catch(SQLException e) {
          throw new EJBException("Could not create: " );
          }
          }


          J2EE Design Patterns: CMP-to-BMP Pattern

          主站蜘蛛池模板: 汉寿县| 博野县| 西华县| 榆树市| 吐鲁番市| 大宁县| 都安| 五莲县| 年辖:市辖区| 全椒县| 读书| 偏关县| 青冈县| 营口市| 页游| 黄大仙区| 阆中市| 颍上县| 西乡县| 台前县| 通辽市| 内江市| 巴里| 虎林市| 永寿县| 济南市| 柏乡县| 东平县| 太白县| 孝义市| 如皋市| 高密市| 南溪县| 营山县| 沙洋县| 三门峡市| 师宗县| 崇左市| 隆昌县| 建宁县| 郯城县|