EJB - 事务

事务是单个工作项单元,遵循 ACID 属性。 ACID 代表原子、一致、隔离和持久。

  • 原子 − 如果任何一个工作项目失败,则整个单元将被视为失败。 成功意味着所有项目都成功执行。

  • 一致 − 事务必须使系统保持一致的状态。

  • 独立 − 每个事务的执行都独立于任何其他事务。

  • 耐用 − 如果事务已被执行或提交,则它应该不会出现系统故障。

EJB 容器/服务器是事务服务器,处理事务上下文传播和分布式事务。 事务可以由容器或 bean 代码中的自定义代码处理来管理。

  • 容器管理的事务 − 在这种类型中,容器管理事务状态。

  • Bean 管理事务 − 在这种类型中,开发人员管理事务状态的生命周期。

容器管理的事务

EJB 3.0 指定了 EJB 容器实现的以下事务属性 −

  • REQUIRED − 表示业务方法必须在事务内执行,否则将为该方法启动一个新事务。

  • REQUIRES_NEW − 表示要为业务方法启动一个新事务。

  • SUPPORTS − 指示业务方法将作为事务的一部分执行。

  • NOT_SUPPORTED − 指示业务方法不应作为事务的一部分执行。

  • MANDATORY − 表示业务方法将作为事务的一部分执行,否则将抛出异常。

  • NEVER − 指示如果业务方法作为事务的一部分执行,则会抛出异常。

示例

package com.tutorialspoint.txn.required;
 
import javax.ejb.*
 
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UserDetailBean implements UserDetailRemote {
	
   private UserDetail;

   @TransactionAttribute(TransactionAttributeType.REQUIRED)
   public void createUserDetail() {
      //create user details object
   }
}

使用Required注解将createUserDetail()业务方法设置为Required。

package com.tutorialspoint.txn.required;
 
import javax.ejb.*
 
@Stateless
public class UserSessionBean implements UserRemote {
	
   private User;

   @EJB
   private UserDetailRemote userDetail;

   public void createUser() {
      //create user 
      //...
      //create user details
      userDetail.createUserDetail();
   }
}

createUser() 业务方法正在使用createUserDetail()。 如果在createUser()调用期间发生异常并且未创建User对象,则也不会创建UserDetail对象。

Bean 管理的事务

在 Bean 管理事务中,可以通过在应用程序级别处理异常来管理事务。

以下是需要考虑的要点 −

  • Start − 何时在业务方法中启动事务。

  • Sucess − 确定提交事务时的成功场景。

  • Failed − 确定事务回滚时的失败场景。

示例

package com.tutorialspoint.txn.bmt;
 
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;
 
@Stateless
@TransactionManagement(value=TransactionManagementType.BEAN)
public class AccountBean implements AccountBeanLocal {
 
   @Resource
   private UserTransaction userTransaction;

   public void transferFund(Account fromAccount, double fund , 
      Account toAccount) throws Exception{

      try{
         userTransaction.begin();

         confirmAccountDetail(fromAccount);
         withdrawAmount(fromAccount,fund);

         confirmAccountDetail(toAccount);
         depositAmount(toAccount,fund);

         userTransaction.commit();
      }catch (InvalidAccountException exception) {
         userTransaction.rollback();
      }catch (InsufficientFundException exception) {
         userTransaction.rollback();
      }catch (PaymentException exception) {
         userTransaction.rollback();
      }
   }

   private void confirmAccountDetail(Account account) 
      throws InvalidAccountException {
   }

   private void withdrawAmount() throws InsufficientFundException {
   }

   private void depositAmount() throws PaymentException{
   }
}

在此示例中,我们利用 UserTransaction 接口通过 userTransaction.begin() 方法调用来标记事务的开始。 我们通过使用 userTransaction.commit() 方法标记事务的完成,如果事务期间发生任何异常,则我们使用 userTransaction.rollback() 方法调用回滚整个事务。