关于EJB--实体Bean的BMP和CMP选择

Posted Thinking-In-java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于EJB--实体Bean的BMP和CMP选择相关的知识,希望对你有一定的参考价值。

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为例: 

Java代码  技术分享
  1. public abstract class AddressEJB implements EntityBean {  
  2.     private EntityContext context = null;  
  3.   
  4.     // getters and setters for PO CMP fields  
  5.   
  6.     public abstract String getFirstName();  
  7.     public abstract void setFirstName(String name);  
  8.     public abstract String getLastName();  
  9.     public abstract void setLastName(String name);  
  10.     public abstract String getStreet1();  
  11.     public abstract void setStreet1(String name);  
  12.     public abstract String getStreet2();  
  13.     public abstract void setStreet2(String name);  
  14.     public abstract String getCity();  
  15.     public abstract void setCity(String name);  
  16.     public abstract String getState();  
  17.     public abstract void setState(String name);  
  18.     public abstract String getCountry();  
  19.     public abstract void setCountry(String name);  
  20.     public abstract String getZip();  
  21.     public abstract void setZip(String name);  
  22.   
  23.     public Object ejbCreate(  
  24.         String fName,  
  25.         String lName,  
  26.         String s1,  
  27.         String s2,  
  28.         String cy,  
  29.         String st,  
  30.         String cnty,  
  31.         String pcode)  
  32.         throws CreateException {  
  33.         setFirstName(fName);  
  34.         setLastName(lName);  
  35.         setStreet1(s1);  
  36.         setStreet2(s2);  
  37.         setCity(cy);  
  38.         setState(st);  
  39.         setCountry(cnty);  
  40.         setZip(pcode);  
  41.         return null;  
  42.     }  
  43.   
  44.     public void ejbPostCreate(  
  45.         String fName,  
  46.         String lName,  
  47.         String street1,  
  48.         String street2,  
  49.         String city,  
  50.         String state,  
  51.         String country,  
  52.         String zip)  
  53.         throws CreateException {  
  54.     }  
  55.     public void setEntityContext(EntityContext c) {  
  56.         context = c;  
  57.     }  
  58.     public void unsetEntityContext() {  
  59.     }  
  60.     public void ejbRemove() throws RemoveException {  
  61.     }  
  62.     public void ejbActivate() {  
  63.     }  
  64.     public void ejbPassivate() {  
  65.     }  
  66.     public void ejbStore() {  
  67.     }  
  68.     public void ejbLoad() {  
  69.     }  
  70. }  


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

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

Java代码  技术分享
  1. <entity>  
  2.   <display-name>AddressEJB</display-name>  
  3.   <ejb-name>AddressEJB</ejb-name>  
  4.   <local-home>com.sun.j2ee.blueprints.address.ejb.AddressLocalHome</local-home>  
  5.   <local>com.sun.j2ee.blueprints.address.ejb.AddressLocal</local>  
  6.   <ejb-class>com.sun.j2ee.blueprints.address.ejb.AddressEJB</ejb-class>  
  7.   <persistence-type>Container</persistence-type>  
  8.   <prim-key-class>java.lang.Object</prim-key-class>  
  9.   <reentrant>False</reentrant>  
  10.   <cmp-version>2.x</cmp-version>  
  11.   <abstract-schema-name>Address</abstract-schema-name>  
  12.   
  13.   
  14.   <cmp-field>  
  15.     <field-name>firstName</field-name>  
  16.   </cmp-field>  
  17.   <cmp-field>  
  18.     <field-name>lastName</field-name>  
  19.   </cmp-field>  
  20.   <cmp-field>  
  21.     <field-name>street1</field-name>  
  22.   </cmp-field>  
  23.   <cmp-field>  
  24.     <field-name>street2</field-name>  
  25.   </cmp-field>  
  26.   <cmp-field>  
  27.     <field-name>city</field-name>  
  28.   </cmp-field>  
  29.   <cmp-field>  
  30.     <field-name>state</field-name>  
  31.   </cmp-field>  
  32.   <cmp-field>  
  33.     <field-name>country</field-name>  
  34.   </cmp-field>  
  35.   <cmp-field>  
  36.     <field-name>zip</field-name>  
  37.   </cmp-field>  
  38.   
  39.   
  40.   <security-identity>  
  41.     <description></description>  
  42.     <use-caller-identity></use-caller-identity>  
  43.   </security-identity>  
  44.   
  45. </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()为例: 

Java代码  技术分享
    1. public Object ejbCreate(  
    2.     String fName,  
    3.     String lName,  
    4.     String s1,  
    5.     String s2,  
    6.     String cy,  
    7.     String st,  
    8.     String cnty,  
    9.     String pcode)  
    10.     throws CreateException {  
    11.   
    12.     // insert row into database  
    13.     this.fName = fName;  
    14.     this.lName = lName;  
    15.     this.s1 = s1;  
    16.     this.s2 = s2;  
    17.     this.cy = cy;  
    18.     this.st = st;  
    19.     this.cnty = cnty;  
    20.     this.pcode = pcode;  
    21.   
    22.     // Insert database record  
    23.     try {  
    24.         Connection connection = getConnection();  
    25.         PreparedStatement statement =  
    26.             connection.prepareStatement(  
    27.                 "INSERT INTO Address (firstName,lastName,street1,street2,city,state,country,zip) VALUES (?, ?, ?,?,?,?)");  
    28.         statement.setString(1, fName);  
    29.         statement.setString(2, lName);  
    30.         statement.setString(3, pcode);  
    31.         statement.setString(4, s1);  
    32.         statement.setString(5, s2);  
    33.         statement.setString(6, st);  
    34.         statement.setString(7, cy);  
    35.         statement.setString(8, cnty);  
    36.         if (statement.executeUpdate() != 1) {  
    37.             statement.close();  
    38.             connection.close();  
    39.             throw new CreateException("Could not create: ");  
    40.         }  
    41.         statement.close();  
    42.         connection.close();  
    43.     } catch (SQLException e) {  
    44.         throw new EJBException("Could not create: ");  
    45.     }  
    46. }  

 

转自 http://gimgen1026.iteye.com/blog/148106




































以上是关于关于EJB--实体Bean的BMP和CMP选择的主要内容,如果未能解决你的问题,请参考以下文章

在不同的 EJB 中获取和处理实体 Bean

EJB_开发单表映射的实体bean

使用MyEclipse开发Java EE应用:用XDoclet创建EJB 2 Session Bean项目

关于 EJB 3.0 和 Toplink 框架的一些限制

组合实体模式

Java组合实体模式~