- 论坛徽章:
- 0
|
EJB bmp-1
public interface javax.ejb.EnterpriseBean implements java.io.Serializable
{
}
EJB bmp-2
public interface javax.ejb.EntityBean implements javax.ejb.EnterpriseBean
{
public void setEntityContext(javax.ejb.EntityContext);
public void unsetEntityContext();
public void ejbRemove();
public void ejbActivate();
public void ejbPassivate();
public void ejbLoad();
public void ejbStore();
}
EJB bmp-3
package examples;
import javax.ejb.*;
import java.rmi.RemoteException;
/**
* 这是AccountBean 的远程接口。
*
* 客户端跟Bean交互时操作这个接口。
* 容器将实现此接口;实现对象称作EJB对象,
* 它向实际的Bean委托调用。
*/
public interface Account extends EJBObject
{
/**
* 存款到账户中,数目为amt。
*/
public void deposit(double amt) throws AccountException, RemoteException;
/**
* 从银行账户中取款,数目为amt 。
* @throw AccountException 当amt小于可用余额时,抛掷异常。
*/
public void withdraw(double amt) throws AccountException, RemoteException;
// 实体Bean域的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;
}
EJB bmp-4
package examples;
import javax.ejb.*;
/**
* 这是AccountBean 的本地接口。
*
* 客户端跟Bean交互时操作这个接口。
* 容器将实现此接口;该实现对象称作本地对象,
* 它向实际的Bean委托调用。
*/
public interface AccountLocal extends EJBLocalObject
{
/**
* 存款到账户中,数目为amt。
*/
public void deposit(double amt) throws AccountException;
/**
* 从银行账户中取款,数目为amt
* @throw AccountException 当amt小于可用余额时,抛掷异常
*/
public void withdraw(double amt) throws AccountException;
// 实体Bean域的Getter/setter方法
public double getBalance();
public String getOwnerName();
public void setOwnerName(String name);
public String getAccountID();
public void setAccountID(String id);
}
EJB bmp-5
package examples;
import javax.ejb.*;
import java.util.Collection;
import java.rmi.RemoteException;
/**
* 这是Account的Home接口。
* 该接口由EJB容器的工具来实现。
* 该实现对象称作Home 对象,它是EJB对象工厂。
*/
public interface AccountHome extends EJBHome
{
/**
* 在此Home接口内定义了一个单独的create()方法,
* 它对应AccountBean 中的ejbCreate()方法。
* 该方法创建了本地EJB对象。
*
* 注意本地Home接口返回一个本地接口,
* 但Bean返回一个主键。
*
* 注意没有抛出RemoteExceptions异常,因为它是本地的。
*
* @param accountID account (unique)的编号。
* @param ownerName 账户拥有人的名字。
* @return 最新创建的本地对象。
*/
Account create(String accountID, String ownerName) throws CreateException, RemoteException;
/**
* 通过主键(Account ID)查找Account。
*/
public Account findByPrimaryKey(AccountPK key) throws FinderException, RemoteException;
/**
* 通过拥有者名字(假设名字惟一)查找Account 。
*/
public Collection findByOwnerName(String name) throws FinderException, RemoteException;
/**
* 这个Home业务方法独立于任何特定的账户。
* 它返回银行内所有账户的总额。
*/
public double getTotalBankValue() throws AccountException, RemoteException;
}
EJB bmp-6
package examples;
import javax.ejb.*;
import java.util.Collection;
/**
* 这是Account的本地Home接口。
* 该接口由EJB容器的工具实现。
* 实现对象称做本地Home对象,它是一个本地EJB对象工厂。
*/
public interface AccountLocalHome extends EJBLocalHome
{
/**
* 在这个Home接口定义了一个单独的create()方法,
* 它对应AccountBean中的ejbCreate()方法。
* 这个方法创建一个本地EJB对象。
*
* 注意本地Home接口返回一个本地接口,
* 而Bean类返回一个主键。
*
* 注意没有抛出RemoteExceptions异常,因为我们是本地的而非远程。
*
* @param accountID account (unique)的编号。
* @param ownerName 账户拥有者的名字。
* @return 最新创建的本地对象。
*/
AccountLocal create(String accountID, String ownerName) throws CreateException;
/**
* 通过主键(Account ID)查找一个Account。
*/
public AccountLocal findByPrimaryKey(AccountPK key) throws FinderException;
/**
* 通过自身的名字(假定名字惟一)查找一个Account。
*/
public Collection findByOwnerName(String name) throws FinderException;
/**
* Home业务方法独立于任何特定的账户实例。
* 它返回银行内所有银行账户的总额。
*/
public double getTotalBankValue() throws AccountException;
}
EJB bmp-7
package examples;
import java.io.Serializable;
/**
* Account的主键类
*/
public class AccountPK implements java.io.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)
{
return ((AccountPK)account).accountID.equals(accountID);
}
}
EJB bmp-8
package examples;
import java.sql.*;
import javax.naming.*;
import javax.ejb.*;
import java.util.*;
import java.rmi.RemoteException;
/**
* 示范Bean管理的持久化实体Bean。
* 这个实体Bean代表一个银行账户。
*/
public class AccountBean implements EntityBean
{
protected EntityContext ctx;
// Bean管理的状态域。
private String accountID; // 主键类
private String ownerName;
private double balance;
public AccountBean()
{
System.out.println("New Bank Account Entity Bean Java Object created by EJB Container.");
}
... 方法继续 ...
EJB bmp-9
... 继续 ...
// 业务逻辑方法。
/**
* 存款到账户,数目为amt 。
*/
public void deposit(double amt) throws AccountException
{
System.out.println("deposit(" + amt + ") called.");
balance += amt;
}
/**
* 从银行账户取款,数目为amt。
* @throw AccountException 当amt小于可用的余额时抛出。
*/
public void withdraw(double amt) throws AccountException
{
System.out.println("withdraw(" + amt + ") called.");
if (amt > balanc) {
throw new AccountException("Your balance is " + balance + "! You cannot withdraw " + amt + "!");
}
balance -= amt;
}
// 实体Bean域的Getter/setter方法。
public double getBalance() {
System.out.println("getBalance() called.");
return balance;
}
public void setOwnerName(String name) {
System.out.println("setOwnerName() called.");
ownerName = name;
}
public String getOwnerName() {
System.out.println("getOwnerName() called.");
return ownerName;
}
public String getAccountID() {
System.out.println("getAccountID() called.");
return accountID;
}
public void setAccountID(String id)
{
System.out.println("setAccountID() called.");
this.accountID = id;
}
/**
* Home逻辑方法是跟特定账户实例无关的。
* 它返回所有银行账户的总额。
*/
public double ejbHomeGetTotalBankValue() throws AccountException
{
PreparedStatement pstmt = null;
Connection conn = null;
try {
System.out.println("ejbHomeGetTotalBankValue()");
/*
* 获得数据库连接。
*/
conn = getConnection();
/*
* 得到所有账号的总额。
*/
pstmt = conn.prepareStatement("select sum(balance) as total from accounts");
ResultSet rs = pstmt.executeQuery();
/*
* 返回总和。
*/
if (rs.next()) {
return rs.getDouble("total");
}
}
catch (Exception e) {
e.printStackTrace();
throw new AccountException(e);
}
finally {
/*
* 释放数据库连接给其他的Bean。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
throw new AccountException("Error!");
}
/**
* 从连接池获取JDBC连接。
*
* @return The JDBC connection
*/
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) {
System.err.println("Could not locate datasource! Reason:");
e.printStackTrace();
throw e;
}
}
}
EJB bmp-10
... 继续 ...
//
// EJB要求的方法。
//
/**
* 被容器调用。执行能够获得所需的资源。
*/
public void ejbActivate()
{
System.out.println("ejbActivate() called.");
}
/**
* 从数据库中删除实体Bean数据。
* 相应地,客户端调用Home.remove()。
*/
public void ejbRemove()
{
System.out.println("ejbRemove() called.");
/*
* 记住一个实体Bean类能够用来代表不同的
* 数据实例。所以,这个方法怎样晓得数据库内
* 哪一个实例将被删除?
*
* 回答是调用实体上下文对象来查询容器。
* 通过从实体上下文获得主键,我们就能
* 知晓是按照主键索引的哪一个数据实例
* 应该从数据库中删除。
*/
AccountPK pk = (AccountPK) ctx.getPrimaryKey();
String id = pk.accountID;
PreparedStatement pstmt = null;
Connection conn = null;
try
{
/*
* 1) 获得一个新的JDBC连接。
*/
conn = getConnection();
/*
* 2) 从数据库中删除账户。
*/
pstmt = conn.prepareStatement("delete from accounts where id = ?");
pstmt.setString(1, id);
/*
* 3) 严重的问题发生时,抛掷一个系统级的异常。
*/
if (pstmt.executeUpdate() == 0) {
throw new RemoteException("Account " + pk + " failed to be removed from the database");
}
}
catch (Exception ex) {
throw new EJBException(ex.toString());
}
finally {
/*
* 4) 释放数据库连接。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
/**
* 被容器调用。释放为钝化而保持的资源。
*/
public void ejbPassivate()
{
System.out.println("ejbPassivate () called.");
}
/**
* 被容器调用。更新内存中的实体Bean对象
* 以反射储存在数据库内的当前值。
*/
public void ejbLoad()
{
System.out.println("ejbLoad() called.");
/*
* 再次查询实体上下文以获得当前主键,
* 这样我们能知晓加载了哪一个实例。
*/
AccountPK pk = (AccountPK) ctx.getPrimaryKey();
String id = pk.accountID;
PreparedStatement pstmt = null;
Connection conn = null;
try {
/*
* 1) 获取一个新的数据库连接。
*/
conn = getConnection();
/*
* 2) 根据accountID从数据库内获得账号。
*/
pstmt = conn.prepareStatement("select ownerName, balance from accounts where id = ?");
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
rs.next();
ownerName = rs.getString("ownerName");
balance = rs.getDouble("balance");
}
catch (Exception ex) {
throw new EJBException("Account " + pk + " failed to load from database", ex);
}
finally {
/*
* 3) 释放数据库连接。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
/**
* 从容器调用。更新数据库以反射内存中的
*实体Bean实例的当前值。
*/
public void ejbStore()
{
System.out.println("ejbStore() called.");
PreparedStatement pstmt = null;
Connection conn = null;
try {
/*
* 1) 获得一个新的数据库连接。
*/
conn = getConnection();
/*
* 2) 存储账号到数据库内。
*/
pstmt = conn.prepareStatement("update accounts set ownerName = ?, balance = ? where id = ?");
pstmt.setString(1, ownerName);
pstmt.setDouble(2, balance);
pstmt.setString(3, accountID);
pstmt.executeUpdate();
}
catch (Exception ex) {
throw new EJBException("Account " + accountID + " failed to save to database", ex);
}
finally {
/*
* 3) 释放数据库连接。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
/**
* 被容器调用。将此Bean跟一个特定的上下文关联起来。
* 我们能够查询Bean的定制属性。
*/
public void setEntityContext(EntityContext ctx)
{
System.out.println("setEntityContext called");
this.ctx = ctx;
}
/**
* 被容器调用。断开Bean实例跟一个特定的上下文环境
* 的联系。
*/
public void unsetEntityContext()
{
System.out.println("unsetEntityContext called");
this.ctx = null;
}
/**
* 在执行ejbCreate()之后调用。现在,Bean能够从上下文
* 获得它的EJBObject,并传递它作为一个“this”参数。
*/
public void ejbPostCreate(String accountID, String ownerName) { }
/**
* 这是对应Home接口中create()方法的初始化方法。
*
* 当客户端调用Home对象的create()方法时,
* Home对象随之调用这个ejbCreate()方法。
*
* @return 账户的主键。
*/
public AccountPK ejbCreate(String accountID, String ownerName)
throws CreateException
{
PreparedStatement pstmt = null;
Connection conn = null;
try {
System.out.println("ejbCreate() called.");
this.accountID = accountID;
this.ownerName = ownerName;
this.balance = 0;
/*
* 获得数据库连接。
*/
conn = getConnection();
/*
* 插入账户到数据库。
*/
pstmt = conn.prepareStatement("insert into accounts (id, ownerName, balance) values (?, ?, ?)");
pstmt.setString(1, accountID);
pstmt.setString(2, ownerName);
pstmt.setDouble(3, balance);
pstmt.executeUpdate();
/*
* 生成主键并返回。
*/
return new AccountPK(accountID);
}
catch (Exception e) {
throw new CreateException(e.toString());
}
finally {
/*
* 为别的Bean释放数据库连接。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
/**
* 通过主键查找账户。
*/
public AccountPK ejbFindByPrimaryKey(AccountPK key) throws FinderException
{
PreparedStatement pstmt = null;
Connection conn = null;
try {
System.out.println("ejbFindByPrimaryKey(" + key + ") called");
/*
* 获得数据库连接
*/
conn = getConnection();
/*
* 在数据库内查找实体
*/
pstmt = conn.prepareStatement("select id from accounts where id = ?");
pstmt.setString(1, key.toString());
ResultSet rs = pstmt.executeQuery();
rs.next();
/*
* 没有错误发生,因此返回主键
*/
return key;
}
catch (Exception e) {
throw new FinderException(e.toString());
}
finally {
/*
* 释放数据库连接供别的Bean使用。
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
/**
* 通过名字查找账户。
*/
public Collection ejbFindByOwnerName(String name) throws FinderException
{
PreparedStatement pstmt = null;
Connection conn = null;
Vector v = new Vector();
try {
System.out.println("ejbFindByOwnerName(" + name + ") called");
/*
* 或别的数据库连接。
*/
conn = getConnection();
/*
* 查找数据库内的主键。
*/
pstmt = conn.prepareStatement("select id from accounts where ownerName = ?");
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
/*
* 插入每个找到的主键到一个vector中
*/
while (rs.next()) {
String id = rs.getString("id");
v.addElement(new AccountPK(id));
}
/*
* 返回主键的vector
*/
return v;
}
catch (Exception e) {
throw new FinderException(e.toString());
}
finally {
/*
* 释放数据库连接给别的Bean
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) {}
try { if (conn != null) conn.close(); }
catch (Exception e) {}
}
}
}
EJB bmp-11
package examples;
/**
* Accounts所抛掷的异常。
*/
public class AccountException extends Exception
{
public AccountException()
{
super();
}
public AccountException(Exception e)
{
super(e.toString());
}
public AccountException(String s)
{
super(s);
}
}
EJB bmp-12
package examples;
import javax.ejb.*;
import javax.naming.*;
import java.rmi.*;
import javax.rmi.*;
import java.util.*;
/**
* 示例客户端代码,它操纵一个银行账户实体Bean。
*/
public class AccountClient
{
public static void main(String[] args) throws Exception
{
Account account = null;
try {
/*
* 获得账户Home对象的引用。
* ——账户EJB对象工厂。
*/
Context ctx = new InitialContext(System.getProperties());
Object obj = ctx.lookup("AccountHome");
AccountHome Home = (AccountHome) javax.rmi.PortableRemoteObject.narrow(obj, AccountHome.class);
System.err.println("Total of all accounts in bank initially = " + Home.getTotalBank-Value());
/*
* 使用工厂创建账户EJB对象。
*/
Home.create("123-456-7890", "John Smith");
/*
* 查找一个账户。
*/
Iterator i = Home.findByOwnerName("John Smith").iterator();
if (i.hasNext()) {
account = (Account) i.next();
}
else {
throw new Exception("Could not find account");
}
/*
* 调用balance()方法并输出结果。
*/
System.out.println("Initial Balance = " + account.getBalance());
/*
* 将$100存入账户。
*/
account.deposit(100);
/*
* 随后取出余额。
*/
System.out.println("After depositing 100, account balance = " + account.getBalance());
System.out.println("Total of all accounts in bank now = " + Home.getTotalBankValue());
/*
* 从EJB对象获得主键。
*/
AccountPK pk = (AccountPK) account.getPrimaryKey();
/*
* 释放旧的EJB对象引用。再次调用find(),
* 这次根据账户ID(比如主键)进行查询。
*/
account = null;
account = Home.findByPrimaryKey(pk);
/*
* 输出当前的余额。
*/
System.out.println("Found account with ID " + pk + ". Balance = " + account.getBalance());
/*
* 试图取出$150。
*/
System.out.println("Now trying to withdraw $150, which is more than is currently available. This should generate an exception..");
account.withdraw(150);
}
catch (Exception e) {
System.out.println("Caught exception!");
e.printStackTrace();
}
finally {
/*
* 永久地销毁实体。
*/
try
{
System.out.println("Destroying account..");
if (account != null)
{
account.remove();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
EJB bmp-13
Account
examples.AccountHome
examples.Account
examples.AccountLocalHome
examples.AccountLocal
examples.AccountBean
Bean
examples.AccountPK
False
jdbc/ejbPool
javax.sql.DataSource
Container
Account
Local
*
Account
Remote
*
Required
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/16182/showart_260637.html |
|