有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在事务上发生了什么。是否在嵌套会话/事务中回滚?

考虑这两个类:EnguleDeLyDaOIMPL和EndoEdAOIMPL。假设如果我想创建一个新员工,我还应该为EmployeeDetail创建一个新记录

考虑到下面的实现,我想知道外部事务(EmployeeDAOImpl的tx)是否由于detailDAO之后发生的任何异常而回滚。create(employeeId)调用,新EmployeeDetail的事务是否也会回滚

public class SessionHandler {
    public static getSession() {
        return Configuration.buildSessionFactory().openSession(); //ignore the isConnected or other exception handling for now
    }
}

public class EmployeeDetailDAOImpl {
    public void create(Serializable employeeId) {
        Session session = SessionHandler().getSession();
        Transaction tx = session.beginTransaction();
        try {
            EmployeeDetail detail = new EmployeeDetail(employeeId);
            session.save(detail );
        } catch (Exception e) {
            if (tx!= null) {
                tx.rollback;
            }
        }
        session.close();
    }
}

public class EmployeeDAOImpl {
    public void add(String name) {
        Session session = SessionHandler().getSession();
        Transaction tx = session.beginTransaction();
        try {
            Employee employee = new Employee(name);
            Serializable employeeId= session.save(employee);
            EmployeeDetailDAOImpl detailDAO = new EmployeeDetailDAOImpl();
            detailDAO.create(employeeId);
            //more things here, that may through exceptions.
        } catch (Exception e) {
            if (tx!= null) {
                tx.rollback;
            }
        }
        session.close();
    }
}

共 (3) 个答案

  1. # 1 楼答案

    事实上,没有一个给出的答案是100%正确的

    这取决于呼叫方/服务

    如果您是从EJB调用方法,那么将有1个事务覆盖这两个方法调用。这样,事务将在出现异常时回滚这两个操作。这背后的原因是EJB中的每个方法都是事务必需的,除非在注释或EJB部署描述符中另有规定

    如果您使用的是spring或任何其他DI框架,那么这取决于您的配置。在正常设置中,调用事务将被挂起,因为JPA EJB将创建自己的事务。但是,您可以使用JTATransactionManager(As specified here)来确保EJB和Springbean共享同一事务

    如果您从POJO调用JPA方法,那么您必须自己处理JTA事务

  2. # 2 楼答案

    是的,它也将回滚实体员工。它甚至不取决于其他实体是否相关。 这取决于交易的范围,这里包括雇员和雇员的详细信息

  3. # 3 楼答案

    您正在为每个方法创建两个不同的事务。因此,回滚不可能发生

    要回滚事务,需要事务中的propogation

    您需要像下面这样编写代码:

    @Transactional(propagation=Propagation.REQUIRED)
    public void testRequired(User user) {
      testDAO.insertUser(user);
      try{
        innerBean.testRequired();
      } catch(RuntimeException e){
        // handle exception
      }
    }
    

    下面是有关传播的更多信息的链接。 http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/transaction/annotation/Propagation.html

    http://www.byteslounge.com/tutorials/spring-transaction-propagation-tutorial