Java EJB3.0和hibernate中的事务管理

Java EJB3.0和hibernate中的事务管理,java,hibernate,ejb-3.0,Java,Hibernate,Ejb 3.0,我试图理解事务管理,并尝试在Struts 2、EJB3和hibernate 5.2中开发的现有应用程序中使用它的功能。 现在我的业务层中有ejb,如下所示 @Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class MyEJb implements ejbxyz { @Override public void method(){

我试图理解事务管理,并尝试在Struts 2、EJB3和hibernate 5.2中开发的现有应用程序中使用它的功能。 现在我的业务层中有ejb,如下所示

   @Stateless
    @TransactionManagement(TransactionManagementType.CONTAINER)
    public class MyEJb implements ejbxyz {

    @Override
    public void method(){
          Dao dao=new Dao() //Dao class is simple java class
          dao.fooMethod();  //this method updates some record
          dao.barMethod();  // this method updates some other record
        }
    } 

    public class Dao{
         fooMethid(){
         Session session=sessFactory.openSession();
          session.beginTransaction();
         session.update(x);
              }
         barMethod(){
              try{
                   Session session=sessFactory.getCurrentSession();
                    session.getNamedQuery("xyz").executeUpdate();

                }catch(HibernateException ex){
                    session.getTransaction.rollback();
                } 
             }
           }
我理解事务管理应该在服务层(在我的例子中是ejb)完成。但是我怎样才能在那里做到这一点呢

现在,依赖项是如果barMethod()无法更新记录,那么我需要回滚在fooMethod中所做的更改。所以基本上我需要在一个事务中完成这两个方法。 当我执行应用程序时,它抛出以下异常

Exception while barMethod getNamedQuery is not valid without active transaction

这是因为我没有在barMethod中开始任何事务。但是我真的不想启动一个新的事务,而是想继续使用fooMethod中启动的旧事务。

容器管理的事务确实是EJB bean的现成支持。但是,您的
Dao
类不是托管bean—它是您手动实例化的常规pojo—因此它不参与由其他ejb启动的任何事务。 因此,将您的
Dao
移动到单独的文件中,用
@Stateless
注释它,然后使用
@EJB私有Dao>将它注入到您的服务中

不过,Ejb容器中的事务还有很多。您可以通过
@TransactionAttribute
注释控制方法级别的事务支持,该注释指定容器应如何调用与事务相关的方法。通过这种方式,您可以控制您的方法是否需要它自己的事务,或者它是否应该参与调用方发起的事务(例如,当从ejbbean调用时)。有关更多信息,请参阅您所说的官方

:事务管理应该在服务层完成。因为您使用的是无状态EJB,它为您启动和提交事务。所以不要在DAO方法中处理事务。对于您来说,事务由EJB容器自动处理。另外,不要使用适当的HibernateAPI。使用JPA。@jbnize请详细说明“不要使用适当的Hibernate API。使用JPA”。hibernate不是JPA实现吗?JavaEE有一个名为JPA的标准规范。它定义了标准接口(EntityManager…)、方法和注释。Hibernate是JPA的一个实现。您应该使用标准API,而不是专有的Hibernate会话API。好的。但是您不认为将dao标记为ejb会增加容器的开销吗?我只是好奇。不是真的,现在你的Dao被分配到你的
MyEjb
,这是一个池,所以每个MyEjb实例都有一个Dao实例。如果将Dao转换为专用bean,它将有自己的池,并将被注入MyEjb。单个托管bean的开销可以忽略不计,并且您的服务器可以愉快地服务数百个bean。专注于您的业务逻辑,让服务器完成它的工作,您可能根本不需要任何性能调整;)