posts - 66,  comments - 11,  trackbacks - 0

    实体Bean包含BMP和CMP两种类型。对BMP实体Bean而言,开发者必须提供各自的数据访问逻辑。为了实现BMP,通常会使用操作数据库的API,比如JDBC.对于CMP实体Bean而言,EJB容器会自动实现数据访问逻辑。这就是CMP的优势所在。通常,只有在应用服务器提供的CMP和目标RDBMS不能满足性能要求时,才去考虑BMP.此时,开发者能够细粒度调整BMP的性能。
    所有的实体Bean类必须实现javax.ejb.EntityBean接口,包括BMP、CMP.EntityBean接口定义了EJB容器对实体Bean组件进行的回调方法,它还可能含有其他方法,比如创建实体Bean,查找实体Bean.
    同ejbCreate()一样,finder方法在Home接口和Bean类中的方法签名不相同:
1、实体Bean实例返回主键给EJB容器,而Home对象返回EJB对象给客户。
2、Bean类和Home类中的finder方法签名,除了Bean类存在ejb前缀外,其他都一样。

    finder方法的工作机制:
1、当客户调用Home对象的finder方法时,Home客户请求实体Bean实例,替它查找到符合客户要求的主键。随后,实体Bean实例将返回主键集合给EJB容器。
2、当EJB容器接收到来自实体Bean实例的主键集合时,它将创建EJB对象结合。注意,它会为各个主键创建EJB对象。最后,容器将EJB对象放着在集合中,并返回给客户。随后,可以调用EJB对象中的方法了。每个EJB对象代表了各个实体Bean实例映射的RDBMS数据。
    finder方法需遵守如下规则:
1、所有的finder方法必须以ejbFind开始
2、实体Bean组件必须提供ejbFindByPrimarKey方法。通过该方法,能够基于客户提供的主键查找到RDBMS中的唯一记录,并映射到实体Bean实例。由于各个实体Bean都存在主键,因此所有实体Bean的Bean类必须支持ejbFindByPrimaryKey方法。
3、可以提供多个finder方法,而且他们的名字、参数都不一样。因此,EJB客户可以使用各种查找策略,以定位到相应的实体Bean实例集合。
4、查找方法必须返回实体Bean的主键。当然,返回值有可能是单个主键,也可能是主键集合。

package com.testproject.ejb.entity;

import java.rmi.RemoteException;

import javax.ejb.EJBObject;
/*
 * 客户将通过这一接口同EJB组件进行交互。
 * EJB容器会实现这一接口。我们将接口实现称之为EJB对象。
 * EJB对象会将请求委派给Bean类。
 
*/

public interface Account extends EJBObject {
    
/**
     * 将amt存入账户
     
*/

    
public void deposit(double amt)throws RemoteException;
    
/**
     * 从银行账户去amount
     
*/

    
public void withdraw(double amount)throws RemoteException;
    
//getter/setter方法,对应于持久化域
    public double getBalance()throws RemoteException;
    
public String getOwnerName()throws RemoteException;
    
public void setOwnerName(String name)throws RemoteException;
    
public String getAccountID()throws RemoteException;
    
public void setAccountId(String id)throws RemoteException;
}


package com.testproject.ejb.entity;

import java.rmi.RemoteException;
import java.util.Collection;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
/**
 * Account的Home接口。
 * EJB容器负责实现它,我们将这一接口的实现称之为Home对象。
 * Home对象充当了EJB对象的工厂。
 
*/

public interface AccountHome extends EJBHome {
    
/**
     * 此时,我们定义了单个create()方法。
     * 对应于AccountBean中的ejbCreate()方法。它负责创建EJB对象。
     
*/

    Account create(String accountID,String ownerName)
throws CreateException,RemoteException;
    
/**
     * 通过主键,查找Account
     
*/

    
public Account findByPrimaryKey(AccountPK key)throws FinderException,RemoteException;
    
/**
     * 通过账户所有人,来查找他的所有账户
     
*/

    
public Collection findByOwnerName(String name)throws FinderException,RemoteException;
    
/**
     * Home业务方法独立于任何帐号,它返回银行帐号的总合。
     
*/

    
public double getTotalBankValue()throws RemoteException;
    
}



package com.testproject.ejb.entity;

import java.io.Serializable;
/**
 * 注意:
 * 1、主键类含有简单字符串accountID.它能够唯一标识银行账号。
 * 2、必须提供toString()方法。EJB容器将调用toString()方法,以获得主键的字符串取值。
 * 3、必须提供hashCode()方法。一旦提供了hashCode()方法,就可以将主键类存放到Hashtable中。EJB
 * 容器需要hashCode()方法。在容器内部,它可能使用Hashtable或类似结构,以存放内存中的所有实体Bean实例
 * 并使用各个主键作为Hashtable的键(key)
 * 4、必须提供equals()方法。在容器比较2个缓存的实体Bean实例时,它会使用equals()方法来比较各自的主键是否相等。
 
*/

public class AccountPK implements Serializable {
    
public String accountID;
    
    
public AccountPK(String id){
        
this.accountID = id;
    }

    
    
public AccountPK(){}
    
    
public String toString(){
        
return accountID;
    }


    
public int hashCode(){
        
return accountID.hashCode();
    }

    
    
public boolean equals(Object account){
        
if(!(account instanceof AccountPK))
            
return false;
        
return ((AccountPK)account).accountID.equals(accountID);
    }

}



package com.testproject.ejb.entity;

import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.RemoveException;
import javax.naming.Context;
import javax.naming.InitialContext;

public class AccountBean implements EntityBean {
    
    
protected EntityContext ctx;
    
    
//BMP持久化域
    private String accountID;
    
private String ownerName;
    
private double balance;
    
    
//业务逻辑方法
    /**
     * 将amt存入账户
     
*/

    
public void deposit(double amt){
        System.out.println(
"deposit("+amt+")called");
        balance 
+= amt;
    }

    
/**
     * 从银行账户去amount
     
*/

    
public void withdraw(double amt){
        System.out.println(
"withdraw("+amt+")called");
        
if(amt>balance){
            
        }

        balance 
-= amt;
    }

    

    
public String getAccountID() {
        
return accountID;
    }

    
public void setAccountID(String accountID) {
        
this.accountID = accountID;
    }

    
public String getOwnerName() {
        
return ownerName;
    }

    
public void setOwnerName(String ownerName) {
        
this.ownerName = ownerName;
    }

    
public double getBalance() {
        
return balance;
    }

    
    
/**
     * Home业务方法独立于任何账号,它返回银行账号的总和
     
*/

    
public double ejbHomeGetTotalBanValue()throws Exception{
        PreparedStatement pstmt 
= null;
        Connection conn 
= null;
        
double total = 0;
        
try{
            System.out.println(
"ejbHomeGetTotalBankValue()");
            
/*获得数据库连接*/
            conn 
= getConnection();
            
/*合计*/
            pstmt 
= conn.prepareStatement("select sum(balance) as total form accounts");
            ResultSet rs 
= pstmt.executeQuery();
            
if(rs.next()){
                 total 
= rs.getDouble("total");
            }

        }
catch(Exception e){
            e.printStackTrace();
            
throw e;
        }

        
        
finally{
            
/*释放资源*/
            
try{if(pstmt!=null)pstmt.close();}
            
catch(Exception e){}
            
try{if(conn!=null)conn.close();}
            
catch(Exception e){}
        }

        
return total;
    }

    
/**
     * 从连接池获得JDBC连接
     
*/

    
public Connection getConnection()throws Exception{
        
try{
            Context ctx 
= new InitialContext();
            javax.sql.DataSource ds 
= (javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/ejbPool");
            
return ds.getConnection();
        }
catch(Exception e){
            e.printStackTrace();
            
throw e;
        }

    }

    
//回调方法先不写了,实在太多
    public void ejbActivate() throws EJBException, RemoteException {
    }


    
public void ejbLoad() throws EJBException, RemoteException {
    }


    
public void ejbPassivate() throws EJBException, RemoteException {
    }


    
public void ejbRemove() throws RemoveException, EJBException,
            RemoteException 
{
    }


    
public void ejbStore() throws EJBException, RemoteException {
    }


    
public void setEntityContext(EntityContext arg0) throws EJBException,
            RemoteException 
{
    }


    
public void unsetEntityContext() throws EJBException, RemoteException {
    }


}

posted on 2009-11-21 12:32 王永庆 阅读(195) 评论(0)  编辑  收藏 所属分类: EJB学习笔记

只有注册用户登录后才能发表评论。


网站导航:
 
<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用链接

留言簿(1)

随笔分类

随笔档案

关注blogs

搜索

  •  

最新评论

阅读排行榜

评论排行榜