JEE Transactional:在哪里指定 dontRollbackOn / rollbackOn
JEE Transactional: where to specify dontRollbackOn / rollbackOn
我对 JEE 事务注释的 rollbackOn 和 dontRollbackOn 的使用有疑问。我做了一些研究,但只找到了关于 topic)
的一般信息
@Transactional(dontRollbackOn = {SomeRuntimeException.class}
哪里can/must我指定注解?有两个选项对我来说很有意义,那么它是哪一个?
- 在 class 中发生 RuntimeException
- "sticky" 方法 - 创建交易时(在我的例子中使用 Requires_new),一旦交易被注释,它就会做出相应的反应并不重要 when/where 异常发生
我真的很喜欢第二个版本,因为我创建了一个新的事务,它是 "handed down" 通过业务层到数据库相关的 classes。两个不同的业务功能使用特定的数据库方法,只有一个需要 "dontRollbackOn" 功能。
但是目前在我的情况下(JBOSS 7 EAP,JEE7,Java 1.8)只有版本 1 有效。我需要注释执行实际数据库查询的方法...
@Transactional(dontRollbackOn = {SomeRuntimeException.class}
public void doSomething(){
...
Query query = this.getEntityManager().createQuery(...);
query.setParameter(...);
queryResult = query.getSingleResult();
}
有人可以分享一些这方面的信息吗?
假设您使用的是默认带有事务处理的 EJB 无状态 bean,您可以使用 Context.setRollbackOnly()
(注入 EJB 上下文,并在您的 catch 块中,将其设置为回滚,如果您需要),或使用您从服务方法中抛出的自定义异常类型,您希望在其中发生回滚。此异常需要存在 @ApplicationException(rollback=true)
注释。第二个选项是如何在 EJB 中处理事务机制的非常方便和干净的方式,因为从您的业务方法的声明中可以清楚地看出它是否在错误时回滚,例如public void handleRegistration() throws MyServiceException
。每当容器遇到服务调用时,会导致您的 MyServiceException,它将回滚当前事务(如果存在)。
如果抛出 RuntimeException
的实例,事务也会回滚
可以在免费电子书中找到更多信息Mastering EJB3
不幸的是,您需要在抛出异常的 EJB 方法上执行此操作。否则,异常传播将在方法调用边界将事务标记为回滚。所以这是你的 post.
的答案 (1)
一些进一步的建议:
处理意外异常的最好方法是让它们冒泡出来,然后在UI边界附近的某个地方处理它们。由于它们出乎意料,您通常不希望提交 任何 事务,因为这会使您的应用程序处于不一致状态。
但是,您的示例代码提供了一个实际可能会出现异常的情况。在这种情况下,您应该在原始方法中处理它们:
try {
Query query = this.getEntityManager().createQuery(...);
query.setParameter(...);
queryResult = query.getSingleResult();
...
} catch (NoResultException e) {
// What are the business rules when NoResultException happens?
} catch (NonUniqueResultException e) {
// What are the business rules when NonUniqueResultException happens?
}
如果一个或两个实际上 意外 那么第一段仍然适用。
我对 JEE 事务注释的 rollbackOn 和 dontRollbackOn 的使用有疑问。我做了一些研究,但只找到了关于 topic)
的一般信息@Transactional(dontRollbackOn = {SomeRuntimeException.class}
哪里can/must我指定注解?有两个选项对我来说很有意义,那么它是哪一个?
- 在 class 中发生 RuntimeException
- "sticky" 方法 - 创建交易时(在我的例子中使用 Requires_new),一旦交易被注释,它就会做出相应的反应并不重要 when/where 异常发生
我真的很喜欢第二个版本,因为我创建了一个新的事务,它是 "handed down" 通过业务层到数据库相关的 classes。两个不同的业务功能使用特定的数据库方法,只有一个需要 "dontRollbackOn" 功能。
但是目前在我的情况下(JBOSS 7 EAP,JEE7,Java 1.8)只有版本 1 有效。我需要注释执行实际数据库查询的方法...
@Transactional(dontRollbackOn = {SomeRuntimeException.class}
public void doSomething(){
...
Query query = this.getEntityManager().createQuery(...);
query.setParameter(...);
queryResult = query.getSingleResult();
}
有人可以分享一些这方面的信息吗?
假设您使用的是默认带有事务处理的 EJB 无状态 bean,您可以使用 Context.setRollbackOnly()
(注入 EJB 上下文,并在您的 catch 块中,将其设置为回滚,如果您需要),或使用您从服务方法中抛出的自定义异常类型,您希望在其中发生回滚。此异常需要存在 @ApplicationException(rollback=true)
注释。第二个选项是如何在 EJB 中处理事务机制的非常方便和干净的方式,因为从您的业务方法的声明中可以清楚地看出它是否在错误时回滚,例如public void handleRegistration() throws MyServiceException
。每当容器遇到服务调用时,会导致您的 MyServiceException,它将回滚当前事务(如果存在)。
如果抛出 RuntimeException
可以在免费电子书中找到更多信息Mastering EJB3
不幸的是,您需要在抛出异常的 EJB 方法上执行此操作。否则,异常传播将在方法调用边界将事务标记为回滚。所以这是你的 post.
的答案 (1)一些进一步的建议:
处理意外异常的最好方法是让它们冒泡出来,然后在UI边界附近的某个地方处理它们。由于它们出乎意料,您通常不希望提交 任何 事务,因为这会使您的应用程序处于不一致状态。
但是,您的示例代码提供了一个实际可能会出现异常的情况。在这种情况下,您应该在原始方法中处理它们:
try {
Query query = this.getEntityManager().createQuery(...);
query.setParameter(...);
queryResult = query.getSingleResult();
...
} catch (NoResultException e) {
// What are the business rules when NoResultException happens?
} catch (NonUniqueResultException e) {
// What are the business rules when NonUniqueResultException happens?
}
如果一个或两个实际上 意外 那么第一段仍然适用。