既然您已经在 第 1 部分 学习了有关 Enterprise JavaBeans (EJB) 容器管理的事务的所有细节,那么您可能对 EJB bean 管理的事务以及如何在 Apache Geronimo 应用服务器中实现它感到好奇。在由三部分组成的 系列文章 的这一期文章(第 2 部分)中,您可以获得所有细节。
简介
本系列分为三部分,将探索 Geronimo 和 OpenEJB 可以为您提供什么帮助,以及在 EJB 2.1 中现在可以实现的 EJB 事务概念(让您顺利进入 EJB 3.0)。第 2 部分(即本文)将详细描述 EJB bean 管理的事务,研究可以生成的两种 bean 管理的事务(Java Transaction API (JTA) 和 Java Database Connectivity (JDBC) 事务)的用法。您将了解这些事务的回滚和如何在 Geronimo 中使用 bean 管理的事务。
现在简要回顾一下第 1 部分中涵盖的内容:使用 EJB 事务,您可以从下列两个选项中进行选择:
您可以将事务实现委托给 EJB 容器。这就是容器管理的事务,也是本系列文章第 1 部分的焦点。请参阅 第 1 部分,获得对事务和容器管理的事务的简介。
在提交事务和将其回滚时,允许通过编程方式管理企业 bean。应用程序开发人员必须明确将事务逻辑编入企业 bean 代码来实现它。这就是 bean 管理的事务,是本系列的第 2 部分(也就是本文)的焦点。
在第 3 部分中,您将了解与容器管理的事务和 bean 管理的事务有关的难题和附加特性。
bean 管理的事务
与 bean 管理的事务相比较,容器管理的事务更简单且代码更少。但是在使用容器管理的事务时存在以下情况:您的企业 bean 方法既可以参与到事务中,也可以不参与。如果您需要更粗略的逻辑,并在基于特定有效性逻辑的情况下使用粗略逻辑提交事务或回滚事务,那么您应该使用 bean 管理的事务。bean 管理的事务可使您对事务边界进行全面控制。
会话 bean 或消息驱动 bean (MDB) 可以使用 bean 管理的事务。实体 bean 不能使用 bean 管理的事务。这是因为 EJB 容器控制了加载或存储实体 bean 的数据的时间。
在 bean 管理的事务中,容器必须允许 bean 实例在一个方法中连续执行几个事务,但是要记住,不能执行嵌套事务。如果您试图启动一个新事务而 bean 实例还没有提交前一个事务,那么容器将抛出一个异常。
您可以使用两种类型的 bean 管理的事务:
JTA 事务
JDBC 事务
我们将在下一节中查看这两种事务。
JTA 事务
JTA 是事务管理器和分布式事务处理系统所涉及的其他组件之间的一个接口规范。通过使用接口,不必使用事务管理器的特有 API 就可以单独地划分事务。
所有 EJB 容器都必须支持 JTA API。对于一名开发人员,这允许您将事务指令传达给 EJB 容器,并以通用、简单的方式提供事务指令。此方法使您不必担心事务服务的底层工作。
javax.transaction.UserTransaction
使用 bean 管理的 JTA 事务时,可使用 javax.transaction.UserTransaction 接口来划分事务。在该接口上,有三个有趣的方法:
begin() —— 创建一个新的事务,并将该事务与当前线程关联起来。
commit() —— 提交与当前线程有关联的事务。
rollback() —— 强行回滚与当前线程有关联的事务。
在 begin() 和 commit() 之间发生的所有更新都是在一个事务中完成的。
UserTransaction 接口上的其他方法包括:
getStatus() —— 检索与当前线程有关的事务的状态。返回值是 javax.transaction.Status 接口上定义的常数。
setRollbackOnly() —— 强行使事务终止。
setTransactionTimeout(int) —— 设置事务中止前能运行的最大次数。这在避免死锁时很有用。
请参阅本文的 参考资料 部分,获得 Sun 公司的 JavaDocs 中有关 UserTransaction 和 UserStatus 接口的链接。
如何使用 bean 方法获得 UserTransaction 的最初引用呢?基于企业 bean 的类型,您可从 bean 上下文中获得接口:
对于会话 bean,可从 javax.ejb.EJBContext 调用 getUserTransaction()。
对于 MDB,可从 MessageDrivenContext.getUserTransaction() 调用 getUserTransaction()。