實體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
王永慶 閱讀(214)
評論(0) 編輯 收藏 所屬分類:
EJB學習筆記