EJB如何管理事务
目录
参考文章
前言:
1. @TransactionManagement
2. @TransactionAttribute
3. @ApplicationException
4. @EJB
5. @Stateless 和 @Stateful
6. @PostConstruct 和 @PreDestroy
7.不使用容器管理事务时,可以使用 @Stateless 吗
1. @Stateless 与事务管理的关系
2. 使用 @Stateless 并启用 Bean 管理事务
3. 如何在 @Stateless 中使用 Bean 管理事务
4. 推荐做法
5. @Stateful 与 Bean 管理事务
总结1
总结2
===
参考文章
JPA、EJB、事务管理、WebSphere ---相关内容整理_ejb jpa-CSDN博客
前言:
在 EJB(Enterprise JavaBeans) 中,事务管理也是一个核心功能。EJB 提供了类似于 Spring 的注解来控制事务行为。以下是 EJB 中常用的与事务管理相关的注解及其作用:
1. @TransactionManagement
作用:指定 EJB 的事务管理方式(容器管理或 Bean 管理)。
类全称:javax.ejb.TransactionManagement
属性:
value:可以是 TransactionManagementType.CONTAINER(容器管理事务,默认)或 TransactionManagementType.BEAN(Bean 管理事务)。
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class MyEJB {
// 业务逻辑
}
===
2. @TransactionAttribute
作用:指定 EJB 方法的事务属性(类似于 Spring 的 @Transactional)。
类全称:javax.ejb.TransactionAttribute
属性:
value:指定事务传播行为,可以是以下枚举值:
TransactionAttributeType.REQUIRED:如果当前存在事务,则加入该事务;否则创建一个新事务。
TransactionAttributeType.REQUIRES_NEW:总是创建一个新事务,如果当前存在事务,则挂起当前事务。
TransactionAttributeType.SUPPORTS:如果当前存在事务,则加入该事务;否则以非事务方式执行。
TransactionAttributeType.NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起当前事务。
TransactionAttributeType.MANDATORY:如果当前存在事务,则加入该事务;否则抛出异常。
TransactionAttributeType.NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
@Stateless
public class MyEJB {
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doSomething() {
// 业务逻辑
}
}
===
3. @ApplicationException
作用:指定某个异常是否触发事务回滚。
类全称:javax.ejb.ApplicationException
属性:
rollback:如果为 true,则当抛出该异常时触发事务回滚;默认为 false。
@ApplicationException(rollback = true)
public class MyException extends Exception {
// 自定义异常
}
===
4. @EJB
作用:用于注入 EJB 实例。
类全称:javax.ejb.EJB
说明:虽然不直接用于事务管理,但在 EJB 中,事务通常是通过容器管理的,因此注入的 EJB 实例会继承容器的事务行为。
@Stateless
public class MyEJB {
@EJB
private AnotherEJB anotherEJB;
public void doSomething() {
anotherEJB.doSomethingElse();
}
}
===
5. @Stateless 和 @Stateful
作用:定义 EJB 的类型(无状态或有状态)。
类全称:
javax.ejb.Stateless
javax.ejb.Stateful
说明:事务行为通常与 EJB 的类型相关。无状态 Bean(@Stateless)通常更适合容器管理事务。
@Stateless
public class MyStatelessEJB {
// 业务逻辑
}
@Stateful
public class MyStatefulEJB {
// 业务逻辑
}
====
6. @PostConstruct 和 @PreDestroy
作用:用于定义 Bean 的生命周期回调方法。
类全称:
javax.annotation.PostConstruct
javax.annotation.PreDestroy
说明:虽然不直接用于事务管理,但这些方法可以在事务开始前或结束后执行一些逻辑
@Stateless
public class MyEJB {
@PostConstruct
public void init() {
// 初始化逻辑
}
@PreDestroy
public void cleanup() {
// 清理逻辑
}
}
7.不使用容器管理事务时,可以使用 @Stateless 吗
在 EJB(Enterprise JavaBeans) 中,@Stateless 注解通常与 容器管理事务(Container-Managed Transactions, CMT) 一起使用,因为无状态 Bean(@Stateless)的设计初衷是让容器管理其生命周期和事务行为。
然而,EJB 规范 也允许在 @Stateless Bean 中使用 Bean 管理事务(Bean-Managed Transactions, BMT),但这并不是推荐的做法。
1. @Stateless 与事务管理的关系
默认行为:@Stateless Bean 默认使用 容器管理事务(CMT),即事务由容器自动管理,开发者无需显式控制事务的开始、提交或回滚。
Bean 管理事务(BMT):如果显式指定为 Bean 管理事务(通过 @TransactionManagement(TransactionManagementType.BEAN)),则开发者需要手动管理事务(使用 UserTransaction)。
2. 使用 @Stateless 并启用 Bean 管理事务
虽然技术上可行,但在 @Stateless Bean 中使用 Bean 管理事务(BMT)并不推荐,原因如下:
无状态性:@Stateless Bean 是无状态的,容器可能会在方法调用之间重用 Bean 实例。如果手动管理事务,可能会导致事务状态不一致。
复杂性:手动管理事务会增加代码的复杂性,容易引入错误(如忘记提交或回滚事务)。
性能问题:手动管理事务可能会导致事务持续时间过长,影响性能。
3. 如何在 @Stateless 中使用 Bean 管理事务
如果确实需要在 @Stateless Bean 中使用 Bean 管理事务,可以按照以下步骤实现:
步骤 1:指定事务管理方式为 BEAN
使用 @TransactionManagement(TransactionManagementType.BEAN) 注解显式指定事务管理方式为 Bean 管理事务。
步骤 2:注入 UserTransaction通过 @Resource 注解注入 UserTransaction 对象,用于手动控制事务。
步骤 3:手动管理事务在方法中显式调用 UserTransaction 的 begin()、commit() 和 rollback() 方法。
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;
@Stateless
@TransactionManagement(TransactionManagementType.BEAN) // 指定为 Bean 管理事务
public class MyStatelessBean {
@Resource
private UserTransaction userTransaction; // 注入 UserTransaction
public void doSomething() {
try {
// 开始事务
userTransaction.begin();
// 业务逻辑
// ...
// 提交事务
userTransaction.commit();
} catch (Exception e) {
try {
// 回滚事务
userTransaction.rollback();
} catch (Exception ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
}
4. 推荐做法
优先使用容器管理事务(CMT):对于 @Stateless Bean,推荐使用容器管理事务,因为容器可以更好地管理事务的生命周期,减少代码复杂性。
仅在必要时使用 Bean 管理事务(BMT):如果确实需要更细粒度的事务控制(例如跨多个方法的事务),可以考虑使用 @Stateful Bean 并启用 Bean 管理事务。
5. @Stateful 与 Bean 管理事务
如果需要在 Bean 中手动管理事务,通常更推荐使用 @Stateful Bean,因为有状态 Bean 可以更好地维护事务状态。
==
import javax.annotation.Resource;
import javax.ejb.Stateful;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;
@Stateful
@TransactionManagement(TransactionManagementType.BEAN) // 指定为 Bean 管理事务
public class MyStatefulBean {
@Resource
private UserTransaction userTransaction; // 注入 UserTransaction
public void doSomething() {
try {
// 开始事务
userTransaction.begin();
// 业务逻辑
// ...
// 提交事务
userTransaction.commit();
} catch (Exception e) {
try {
// 回滚事务
userTransaction.rollback();
} catch (Exception ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
}
}
==
总结1
EJB 提供了 @TransactionManagement 和 @TransactionAttribute 等注解来控制事务行为。
事务管理方式可以是容器管理(默认)或 Bean 管理。
事务传播行为通过 TransactionAttributeType 枚举类来配置。
EJB 的事务管理与 Spring 的事务管理类似,但 EJB 更依赖于容器(如 Java EE 应用服务器)。
===
总结2
@Stateless Bean 可以使用 Bean 管理事务(BMT),但不推荐这样做,因为无状态 Bean 的设计初衷是让容器管理事务。
推荐使用容器管理事务(CMT),因为它更简单、更安全。
如果需要手动管理事务,建议使用 @Stateful Bean。
如果你有更多问题或需要进一步的帮助,请告诉我!