1 / 140

8. 实体 bean - BMP

8. 实体 bean - BMP. 8.4 bean 管理的持久性 bean. BMP ( bean -managed persistence ) 是指在实体 bean 中,所有与关系数据源相关的数据插入、删除、查询与更新操作都是由实体 bean 开发者完成。而在 CMP 中,上述这些操作都是由 EJB 容器使用基于部署描述器的信息,将 EJB 类字段映射到关系数据库的列中,然后使用这些映射关系产生 SQL 代码,从而使得容器能够提供这种功能的实现。. 8. 实体 bean - BMP. Home 接口. Home 接口必须遵守以下规定:

tarika
Download Presentation

8. 实体 bean - BMP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 8. 实体bean-BMP 8.4 bean管理的持久性bean BMP(bean -managed persistence)是指在实体bean中,所有与关系数据源相关的数据插入、删除、查询与更新操作都是由实体bean开发者完成。而在CMP中,上述这些操作都是由EJB容器使用基于部署描述器的信息,将EJB类字段映射到关系数据库的列中,然后使用这些映射关系产生SQL代码,从而使得容器能够提供这种功能的实现。

  2. 8. 实体bean-BMP • Home接口 • Home接口必须遵守以下规定: • 类型为interface; • 必须是public • 必须直接或间接继承javax.ejb.EJBHome接口, EJBHome继承自java.rmi.Remote。

  3. 8. 实体bean-BMP • 声明一个至多个finder函数,函数名称须以find开头接着名称,如findByName()。Finder函数至少包含findByPrimaryKey(),且返回类型必须是bean的remote interface。声明的所有finder函数必需在bean类内定义并实现。

  4. 8. 实体bean-BMP • 声明一个至多个create()函数,返回值类型必须是bean的Remote Interface。每一个create()函数都必须对应于Bean class内定义的ejbCreate()函数和ejbPostCreate(),须有相同的传入参数,且create()函数声明所丢出的例外类必须包含ejbCreate()函数内所丢出的例外类。

  5. 8. 实体bean-BMP • 至少要声明Create()函数和finder()函数其中一项。 • Create() 和finder()函数丢出的例外必须包含java.rmi. RemoteException,finder()函数须另外包含javax.ejb.FinderException。 当调用create()函数时,EJB容器会调用bean类内对应的ejbCreate(),并执行数据表记录的添加。

  6. 8. 实体bean-BMP 只要是属于多笔记录的查询,返回值类型就必需是java.util.Collection或继承自它的Class类型,EJB容器会将查询结果(bean的remote接口)放入Collection中然后返回。 在bean类内实现任何相对应ejbFinderMethod()函数时,属于多笔查询的finder函数应返回包含多笔记录primary key类型的Collection或是继承自它的Class对象,而单笔查询则返回primary key的值或是primary key类型的对象。

  7. 8. 实体bean-BMP • Remote接口 Remote 接口必须遵守以下规定: • 类型为interface; • 必须是public; • 必须直接或间接继承javax.ejb.EJBObject。 EJBObject继承自java.rmi.Remote。

  8. 8. 实体bean-BMP • 每一个声明在Remote接口的business函数,在Bean类内都必须有相应的实现,函数名称要一样,并具有相同的传入参数及返回值类型,且business函数声明所丢出的例外类,必须包含java,rmi.RemoteException和对应于Bean类的business函数所有丢出的例外类。

  9. 8. 实体bean-BMP • 只要在Renote接口声明了business methods,那么就必须在bean类内有相对应的定义与实现。 business methods可返回值如下: • Primitive type(integer) • Home interface • Romote interface • Implement java.io.Serializable的class • 内容为上述类型的array或是java.util.collection、Enumination、Vector和Hashtable等。

  10. 8. 实体bean-BMP • Bean类 • 类型为class; • 必须是public; • 定义一个没有参数的构造器(constructor); • 必须直接或间接实现javax.ejb.EntityBean接口。 EntityBean继承自javax.ejb.EnterpriseBean,而EnterpriseBean继承自java.io.Serializable。

  11. 8. 实体bean-BMP • 必需实现所有callback函数内所需要的数据库存取(CMP不需要); • 必需实现在Home接口内声明的finder函数(CMP不需要),且要以“ejbFind”为finder函数名称的开头。 • 实现在Remote接口内声明的business函数,且名称要与Remote 接口内声明的名称一样,相同的传入参数及返回值类型。

  12. 8. 实体bean-BMP import javax.ejb.*; public class UserEJB implements EntityBean { public class setEntityContext(Entitycontext ctx) { // 可在此设置数据库的链接 …… } public class unsetEntityContext() { // 可在此关闭在setEntityContext所设置数据库的链接 …… }

  13. 8. 实体bean-BMP public PrimaryKeyType ejbCreate(…) { throws DuplicateKeyException, CreateException { // insert记录至数据库的表格 return PrimaryKey; } public void ejbPostCreate(…) { …… } public void ejbActivate() { // 取得数据库的表格的PrimaryKey …… }

  14. 8. 实体bean-BMP public void ejbPassivate() { …… } public void ejbRemove() { // delete数据库的表格记录 } public void ejbLoad() { // 读取数据库的表格记录,并更新字段变量 } public void ejbStore() { // update数据库的表格记录 }

  15. 8. 实体bean-BMP public PrimaryKeyType ejbFindByPrimary() { // 根据PrimaryKey选取数据库的表格记录 } public PrimaryKeyType_or_Collection ejbFindByMethod() { // 选取数据库的表格记录 }

  16. 8. 实体bean-BMP 实现实体Bean接口定义的九个callback函数: setEntityContext()、unsetEntityContext() ejbCreate()、ejbPostCreate() ejbActivate()、 ejbPassivate() ejbRemove()、ejbLoad()、ejbStore() 上述九个回调函数都要声明成public,且除了ejbCreate()函数要返回Primary key类的类型外,其余的返回值都是void。

  17. 8. 实体bean-BMP • BMP实体bean的生命周期 BMP的实体bean的生命周期也分为三种状态:  Does not exist  Pooled state  Ready State 虽然BMP的实体bean数据库存取都是在bean类内,由开发人员自行定义,但是bean的生命周期仍是由EJB容器来控制。

  18. Does Not Exist (不存在) 取削数据库链接 取得数据库链接 1.newInstance() 2.setEntityContext() unsetEntityContext() 选取数据表格记录 Pooled (池态) ejbFindMethod() 添加数据表格记录 1. ejbActivate() 2. ejbLoad() ejbRemove() 1. ejbStore() 2. ejbPassivate() 1. ejbCreate() 2. ejbPostcreate() 删除数据表格记录 Ready (预备状态) ejbLoad() ejbStore() 读取数据表格记录 保存数据表格记录 Business_method()

  19. 8. 实体bean-BMP • 回调方法 • setEntityContext:当bean实例被建立后,EJB容器调用该方法,提供一些存取与bean实例执行时期相关信息的函数。如:getEJBHome()可以取得bean实例的Home接口;getEJBObject()函数可以取得与bean实例相关联的EJB Object。

  20. 8. 实体bean-BMP 当需要在其它bean实例的函数内取得上述信息时,可以在setEntityContext()函数内将传入的EntityContext对象指定bean实例中的变量: private EntityContext ctx; public setEntityContext(EntityContext ctx){ this.ctx=ctx; }

  21. Bean Instance Bean Instance Bean Instance Class.newInstance() Bean Instance 执行setEntityContext()函数 实例池 setEntityContext()函数的执行时机

  22. public String user_id; public String password; public String name; private connection con; private String DBJndi=“java:comp/env/jdbc/ExampleDB”; private String dbID=“guest”; private StringdbPassword=“guest123”; private StringtableName=“UserTBL”; private Entitycontext context; public void setEntitycontext(Entitycontext context) { this.context=context; try { InitialContext ictx=new InitialContext(); DataSource ds=(DataSource)ictx.lookup(DBJndi); con=ds.getConnection(dbID, dbPassword); } catch (Exception ex) { throw new EJBException(ex.getMassage()); } }

  23. 8. 实体bean-BMP • unsetEntityContext() 相对于setEntityContext()函数,EJB容器会在删除bean实例前调用unsetEntityContext()函数。因此在执行该函数时,应将在setEntityContext()函数内设置的一些共用资源都删除掉。

  24. 8. 实体bean-BMP public void unsetEntitycontext() { context=null; try { con.close(); } catch (SQLException ex) { throw new JBException(ex.getMassage()); } }

  25. Bean Instance Bean Instance Bean Instance Bean Instance Bean Instance 实例池 EJB Object 1 Bean Instance 2 执行unsetEntityContext()函数 3 unsetEntityContext()函数的执行时机 实例池 Bean Instance

  26. 8. 实体bean-BMP • ejbCreate() 当客户端调用Home接口的create()函数时,EJB容器会调用对应于bean实例中的具有相同传入参数的ejbCreate()函数。在BMP的情况下, ejbCreate()函数负责向数据库添加新的实体,相比之下,CMP情况下的ejbCreate()函数只需初始化一些字段,因此简单很多。 EJB规范规定BMP下的ejbCreate()函数必须返回新创建的主键。

  27. EntityHome.create()函数 1 Bean Instance Bean Instance Bean Instance 调用ejbCreate()函数 2 insert 添加记录至数据库中的数据表格,并设置bean的表格字段变量值 Database 实例池 3 ejbCreate()函数的执行时机 EJB Object 4 调用ejbPostCreate()函数 Bean Instance 8. 实体bean-BMP

  28. public ShipPK ejbCreate(int id, String name, int capacity, double tonnage) thrpws CreateException { if ((id<1) || (name= = null)) throws new CreteException(“Invalid Parameters”); this.id=id; this.name=name; this.capacity=capacity; this.tonnage=tonnage;   Connection con=null; PreparedStatement ps=null; try { con=this.getConnection(); ps=con.preparedStatement(“insert into Ship(id, name, capacity, tonnage)”+ “ value (?,?,?,?)”); ps.setInt(1, id); ps.setString(2, name); ps.setInt(3, capacity); ps.setDouble(4, tonnage);

  29. if (ps.executeUpdate() != 1) { throw new CreateException (“Failed to add ship to database”); } ShipPK primaryKey=new ShipPK(); PrimaryKey.id=id; return primaryKey; //CMP的情况下返回的是null。 }//try catch (SQLException se) { throw new EJBException(se); } finally { try { if (ps != null) ps.close; if (con !=null) con.close(); } catch (SQLException se) { se.printAtackTrace(); } } }

  30. 8. 实体bean-BMP 说明: 当insert操作失败时,将抛出一个CreateException异常,而不是EJBException异常。原因是:当记录插入失败时,JDBC子系统并没有抛出异常,因此该异常应理解为一个应用程序错误。抛出CreateException异常为应用程序提供了一个从错误中恢复的机会。

  31. 8. 实体bean-BMP • ejbPostCreate() EJB容器调用对应于ejbCreate()函数的ejbPostCreate()函数,来获取与bean有关的信息。此时,bean实例已经由pooled 状态转为ready 状态。 因此在ejbPostCreate()函数内可以调用EntityContext的getPrimaryKey()函数取得bean实例的primary key和调用getEJBObject()函数,取得与其相关联的EJB Object。容器将EJB Object的stub返回给客户端。

  32. 实例池 Bean Instance Bean Instance Bean Instance EJB Object 1 2 调用ejbActivate()函数 3 调用ejbLoad()函数 { 将bean实例的表格字段 变量更新为目前数据库 中的数据表格字段值 } select Database Bean Instance 8. 实体bean-BMP • ejbActivate() ejbActivate()函数的执行时机

  33. 8. 实体bean-BMP CMP情况下的执行顺序:  在bean实例上调用ejbActivate()函数。  持久性字段自动同步。  ejbLoad()函数通知bean它的持久性字段同步完成。  根据需要调用商务方法。 BMP情况下的执行顺序:  在bean实例上调用ejbActivate()函数。  调用ejbLoad()函数让bean同步它的持久性字段。  根据需要调用商务方法。

  34. 1 Bean Instance Bean Instance Bean Instance 调用ejbStore()函数 { 将表格字段变量值写入 数据库中的数据表格字段 } update Database 2 调用ejbPassivate()函数 实例池 3 EJB Object Bean Instance 8. 实体bean-BMP • (6)ejbPassivate() ejbPassivate()函数的执行时机

  35. 8. 实体bean-BMP CMP情况下的执行顺序:  调用ejbStore()函数。  bean实例的persistence field,写入数据库中的数据表字段。 调用ejbPassivate()函数。  将bean实例放回pool。 BMP情况下的执行顺序:  调用ejbStore()函数,以便将bean实例的persistence field写入数据库中的数据表字段。  调用ejbPassivate()函数。  将bean实例放回pool。

  36. 8. 实体bean-BMP • ejbLoad()和ejbStore() 在CMP情况下,bean和数据库的同步是自动发生的,容器自动处理。 在BMP情况下,程序开发者要负责同步工作的完成:bean必需直接读写数据库。容器与bean管理的实体紧密协同工作,并通过两个回调函数ejbLoad()和ejbStore()来通知实体什么时候应该同步它们的状态。

  37. 调用ejbLoad() { 将bean实例的表格字段变量更新 为目前数据库中的数据表格栏值 } SELECTtable_fields 执行business函数 Database 调用ejbStore() { 将表格字段变量值写入 数据库中的数据表格栏 } UPDATEtable_fields 8. 实体bean-BMP ejbLoad()和ejbStore()函数的执行时机

  38. 8. 实体bean-BMP ejbLoad() 和ejbStore()是在business函数被调用时,EJB容器会自动执行的函数,其目的是让bean实例的表格字段变量和数据库的数据表字段值维持一致性,以确保business函数在执行时,所读取的表格字段变量是目前的最新值,而在business函数执行完后,立即将变更后的值写入数据库,以便让其它人读取时亦是目前的最新值。

  39. 8. 实体bean-BMP public void ejbLoad() { ShipPK pk = (ShipPK) context.getPrimaryKey(); connection con=null; PreparedStatement ps = null; ResultSet result = null; try { con = this.getConnection(); ps =con.prepareStatement( “select name, capacity, tonnage from ship where id = ?”) ps.setInt(1, pk.id); result = ps.executeQuery(); if (resule.next()) { id=pk.id; name=result.getString(“name”); capacity=result.getInt(“capacity”); tonnage=result.getDouble(“tonnage”);

  40. 8. 实体bean-BMP } else { throw new EJBException(); } } catch (SQLException se) { throw new EJBException(se); } finally { try { if (result != null) result.close(); if (ps !=null) ps.close(); if (con !=null) con.close(); } catch (SQLException se) { se.printStackTrace(); } } }

  41. 8. 实体bean-BMP public void ejbStore() { Connection con=null; PreparedStatement ps = null; ResultSet result = null; try { con = this.getConnection(); ps =con.prepareStatement ( “updat Ship set name = ?, capacity =?,” + “tonnage = ? where id = ?”); ps.setString (1, name); ps.setInt (2, capacity); ps.setDouble (3, tonnage); ps.setInt(4, id); if (ps.executeUpdate() != 1) { throw new EJBException(“ejbStore”); } }

  42. 8. 实体bean-BMP } catch (SQLException se) { throw new EJBException(se); } finally { try { if (ps !=null) ps.close(); if (con !=null) con.close(); } catch (SQLException se) { se.printStackTrace(); } } }

  43. 8. 实体bean-BMP • ejbRemove() 除了处理bean自己的插入和更新操作外,bean管理的实体还要处理它们自己的删除操作。当客户端应用程序调用EJB home 或EJB对象上的删除函数时,函数调用通过调用ejbRemove()函数转送到bean管理的实体上。bean的开发者负责实现从数据库中删除实体数据的ejbRemove函数。

  44. EntityHome.remove() 或是EntityObject.remove() Bean Instance Bean Instance Bean Instance 1 2 调用ejbRemove() { 将对应于bean实例的记录从数据库表格中删除掉 } delete Database 实例池 2 EJB Object Bean Instance ejbRemove()函数的执行时机 8. 实体bean-BMP

  45. 8. 实体bean-BMP public void ejbRemove() { Connection con=null; PreparedStatement ps = null; try { con = this.getConnection(); ps =con.prepareStatement ( “delete from Ship where id = ?”); ps.setInt (1, id); if (ps.executeUpdate() != 1) { throw new EJBException(“ejbRemove”); } }

  46. 8. 实体bean-BMP } catch (SQLException se) { throw new EJBException(se); } finally { try { if (ps !=null) ps.close(); if (con !=null) con.close(); } catch (SQLException se) { se.printStackTrace(); } } }

  47. 8. 实体bean-BMP • ejbFindByPrimaryKey()和ejbFindMethod() CMP的实体bean并不需要在bean 类内实现任何相对应的ejbFindMethod()函数,它是在bean部署时才产生。BMP的实体bean必需一一实现Home接口中所声明的findeMethod()函数。即home接口中每个名叫findlooku-type()的函数,必需与bean的实现类中的ejbFindlook-type()函数相对应,并且有相同的参数并抛出同样的异常。

  48. EntityHome.findMethod() 实例池 1 Bean Instance Bean Instance Bean Instance Bean Instance Bean Instance Bean Instance EJB Object 2 select Database 调用ejbfindMethod()函数 实例池 3 EJB Object Bean Instance Bean Instance findMethod()函数的执行时机 8. 实体bean-BMP

  49. 8. 实体bean-BMP public ShipPK ejbFindByPrimaryKey(ShipPK primaryKey) throws FinderException { Connection con = null; PreparedStatement ps = null; ResultSet result = null; try { con = this.getConnection(); ps =con.prepareStatement( “select id from Ship where id = ?”) ps.setInt(1, primaryKey.id); result = ps.executeQuery(); // Does ship id exist in database? if (!result.next()) { throw new ObjectNotFoundException (“Cannot find Ship whit id =” + id); }

  50. 8. 实体bean-BMP } catch (SQLException se) { throw new EJBException(se); } finally { try { if (result != null) result.close(); if (ps !=null) ps.close(); if (con !=null) con.close(); } catch (SQLException se) { se.printAtackTrace(); } } return primaryKey; }

More Related