EJB 数据库应用的例子


  下面以一个简单的例子 "银行帐户"应用系统来介绍 EJB 组件的Entity bean类型的组件存取数据库。

  Entity bean 的状态存储在关系数据库的 ACCOUNT 表中,表ACCOUNT 由下面的SQL 语句创建:
  CREATE TABLE ACCOUNT
    (id VARCHAR(3) CONSTRAINT pk_account PRIMARY KEY,
    firstname VARCHAR(24),
    lastname VARCHAR(24),
    balance DECIMAL(10.2));
  和其他EJB 组件一样,开发人员必须编写 Entity bean 的 Entity Bean Class 代码(AccountEJB.java)、Home Interface 代码(AccountHome.java)及Remote Interface 代码(Account.java)。

  Entity Bean Class 代码( AccountEJB.java)

  EntityBean 接口方法
  EjbCreate 方法:当客户端调用 create 方法时,EJB 容器调用相应的ejbCreate 方法。一个Entity组件的ejbCreate 方法要实现下列工作:
  ? 插入Entity Bean 的状态到数据库中
  ? 初始化实例变量
  ? 返回主键。

  AccountEJB的ejbCreate 方法调用insertRow 方法,而insertRow 方法发出一个 insert SQL 语句插入Entity Bean 的状态到数据库中,下面是 Account 类中ejbCreate 方法的源代码:
  sublic String ejbCreate (String id,String firstName,String lastName,double balance)
    throw CreateException{
    if (balance < 0.00){
      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;
  }
  throws 子句可以包含 javax.ejb.CreateException 和别的应用系统中指定的例外处理例程(exceptions)。
Entity Bean的状态也可以通过非 J2EE 应用系统直接插入到数据库中,如SQL 语言脚本插入一行数据到 ACCOUNT表中,尽管这条数据不是通过 ejbCreate 方法插入到数据库中的,但Entity Bean 同样能通过客户端程序定位这条数据。

  ejbPostCreate 方法
  对于每一个ejbCreate 方法,开发人员必须在Entity Bean中写一个ejbPostCreate 方法,EJB 容器在调用完ejbCreate 以后,就立即调用ejbPostCreate ,和 ejbCreate 方法不一样,ejbPostCreate 方法可以调用 getPrimaryKey 等方法,通常ejbPostCreate 方法是空的。

  ejbRemove 方法
  当客户端通过调用 remove 方法来删除一个 Entity Bean 的状态数据时,EJB 容器调用 ejbRemove 方法,ejbRemove 方法从数据库中删除一个Entity Bean 状态数据。代码如下:
  public void ejbRemove() {
    try {
      deleteRow(id);
    } catch (Exception ex){
      throw new EJBException ex("ejbRemove:"+exgetmessage());
    }
  }

  如果ejbRemove 方法遇到系统级错误,将执行javax.ejb.EJBException. 如果遇到应用级错误,将执行javax.ejb.RemoveException。
  entity bean 的状态数据也可以通过数据库的 delete 语句直接删除数据。

  EjbLoad 方法和 ejbStore 方法
  EJB 容器需要维持 Entity Bean 的实例变量与数据库中相应值的同步,这需要调用 ejbLaod 方法和ejbStore 方法。ejbLoad 方法用数据库中的数据刷新变量的值,ejbStore 方法把变量的值写入到数据库中。客户端不能调用  
ejbLoad 方法和ejbStore 方法。
  如果业务处理的方法关系到事物处理,EJB 容器要在业务处理方法调用之前调用 ejbLoad 方法刷新数据,业务处理方法执行之后,EJB 容器又立即调用 ejbStore 方法把数据存储到数据库中。因为 EJB 容器调用ejbLoad方法和ejbStore 方法,开发人员在业务处理方法中不必刷新和存储实例变量的值。
  如果ejbLoad 方法和ejbStore 方法不能在低层数据库中定位 Entity Bean,将执行 javax.ejb.NoSuchEntityException。
  在 AccountEJB 类中,ejbLoad 方法调用 loadRow 方法,loadRow 则发出一个 select 语句从数据库提取数据分配给实例变量;ejbStore 方法调用 storeRow 方法,storeRow 方法则用 update 语句把实例变量的值存储到数据库。代码如下:

  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 方法 :
  Finder 方法允许客户端查找 entity bean ,AccountClient 中有三种方法查找entity bean:
    Account jones = home.findByPrimaryKey("836");
    Collection c home.findByLastName("Smith");
    Collection c home.findInRange(20.00,99.00);
  Entity bean 类必须实现相应的方法,并且文件名以ejbFind 前缀开始,如:AccountEJB 类实现 ejbFindByLastName 的方法如下:
  public Collection ejbFinfBylastName(String lastName)
    throw FinderException {
    Collection result;
    Try {
      Result = selectByLastName(lastName);
    } catch (Exception ex) {
      throw new EJBException("ejbFindByLastName" + ex.getMessage());
    }
    if (result.isEmpty()){
      throw new ObjectNotFoundException("No row found.");
    }
    else {
      return result;
    }
  }

  应用系统中特定的 finder ,如 ejbFindByLastName 和ejbFindInRange,是可选的,但是必须含有 ejbFindByPrimaryKey 方法,ejbFindByPrimaryKey 方法用主键作参数,用来定位一个 entity bean 的状态数据,下面是 ejbFindByPrimaryKey 方法的代码:
  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.");
    }
  }

  ejbFindByPrimaryKey 方法以 primaryKey 作为参数并返回它的值。
注意:1.只有 EJB 容器可以调用ejbFindByPrimaryKey,而客户端不能直接调用 ejbFindByPrimaryKey 方法,客户端只能调用在 home 接口中定义的 findByPrimaryKey。
   2.在 entity bean 类中开发人员必须实现ejbFindByPrimaryKey 方法。
   3.一个 finder 方法的名字必须以 ejbFind 作为前缀。
   4.返回值必须是主键或者是一个主键的集合。

  throw 子句可以包含 javax.ejb.FinderException,和其他别的例外处理例程。如果一个finder 方法只要求返回唯一一个主键,如果主键不存在,则应该执行 javax.ejb.ObjectNotFoundException,ObjectNotFoundException 是FoundException的一个子类;如果 finder 方法要求返回的是一个主键的集合,则应该执行 FinderException 来处理。

  业务处理方法

  业务处理方法包含想在 Entity Bean 中实现的业务处理逻辑。通常业务处理方法不存取数据库,这允许开发人员可以把业务处理逻辑从数据库存取中独立出来。
  在 AccountEJB entity bean 中包含下面的业务处理方法:
  public void debit(double amount)
    throw InsufficientBalanceException {
    if (balance - amount <0){
      throw new InsufficientBalanceException();
    }
    balance -= amount;
  }

  public void credit (double amount) {
    balance += amount;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public double getBalance() {
    return balance;
  }

  AccountClient 程序中调用业务处理方法:
    Account duke = home.create("123","Duke","Earl",0.00);
    Duke.credit(88.50);
    Duke.debit(20.25);
    Double balance = duke.getBalance();
注意:1、业务处理方法的名称不能和 EJB 体系中定义的方法的名称冲突,其他的要求和 entity bean 和 sesson bean 中其它方法的要求相同。
   2、可以在throw 子句中包含应用程序定义的例外处理例程,如 debit 方法执行InsufficientBalanceException。为了识别系统级错误,业务处理逻辑应该调用 javax.ejb.EJBException。

下面是对 AccountEJB 类中存取数据库的总结:


  因为业务处理方法中不需要存取数据库,所以在 AccountEJB 类中的业务处理方法没有存取数据库。但业务处理方法可以通过 EJB 容器调用 ejbStore 来修改实例变量。当然开发人员也可以在 AccountEJB 类的业务处理方法中存取数据库,这依赖于应用程序的具体要求,在存取数据库之前必须连接数据库。

  Home 接口(Interface)
  
  在home 接口中定义让客户端创建和查找 entity bean 的方法。Account Home 接口如下:
  import java.util.Collection;
  import java.rmi.RemoteException;
  import javax.ejb.*;

  public interface AccountHome extends EJBHome {
    public Account create(String id, String firstName, String lastName, double balance)
      throws RemoteException, CreateException;
 
    public Account findByPrimaryKey(String id)
      throws FinderException, RemoteException;
  
    public Collection findByLastName(String lastName)
      throws FinderException, RemoteException;

    public Collection findInRange(double low, double high)
      throws FinderException, RemoteException;
  }
  在Home 接口中,每一种finder 方法必须和 entity bean 类中的 finder 方法对应;finder 方法的名称必须以 find 开始,就象 entity bean 类中的 finder 方法必须以 ejbFind 一样,例如:AccountHome 类中定义的findByLastName 方法和AccountEJB 类中实现的 ejbFindByLastName 方法。

  Remote 接口
  
  Remote 接口定义客户端可以调用的业务处理方法,Account remote 接口的代码如下:

  import javax.ejb.EJBObject;
  import java.rmi.RemoteException;

  public interface Account extends EJBObject {
    public void debit(double amount)
      throws InsufficientBalanceException, RemoteException;
    public void credit(double amount)
      throws RemoteException;

    public String getFirstName()
      throws RemoteException;

    public String getLastName()
      throws RemoteException;

    public double getBalance()
      throws RemoteException;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值