Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate-使用编程事务习惯用法的CMT EJB_Hibernate_Jakarta Ee_Jpa_Transactions_Ejb - Fatal编程技术网

Hibernate-使用编程事务习惯用法的CMT EJB

Hibernate-使用编程事务习惯用法的CMT EJB,hibernate,jakarta-ee,jpa,transactions,ejb,Hibernate,Jakarta Ee,Jpa,Transactions,Ejb,在CMT(EJB3)中使用以下编程事务和会话习惯用法,并将Hibernate Core设置为使用CMT时会发生什么情况? 假设需要当前CMT事务,并使用默认值@TransactionAttribute(必需) hibernate事务是否会在beginTransaction()上加入当前CMT commit()会立即提交hibernate事务还是等到当前CMT提交 在CMT中关闭会话时会发生什么 B.行为是否取决于当前会话是否使用getCurrentSession()绑定到CMT 在我的应用程序中

在CMT(EJB3)中使用以下编程事务和会话习惯用法,并将Hibernate Core设置为使用CMT时会发生什么情况?
假设需要当前CMT事务,并使用默认值
@TransactionAttribute(必需)

  • hibernate事务是否会在
    beginTransaction()
    上加入当前CMT
  • commit()
    会立即提交hibernate事务还是等到当前CMT提交
  • 在CMT中关闭会话时会发生什么
  • B.行为是否取决于当前会话是否使用
    getCurrentSession()
    绑定到CMT

    在我的应用程序中,目前我使用的是一个数据库,使用Hibernate的编程JDBC事务可以很好地工作。现在,应用程序还将JMS队列用于邮件消息传递,并希望将其合并到全局CMT事务中

    编辑:

    目前,我根本没有在应用程序中使用EntityManager,并且希望代码能够移植到非托管环境

    Hibernate配置
    Hibernate.cfg.xml
    启用CMT:

    冬眠4.2.6和玻璃鱼3.1.2

    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.autocommit">false</property>
    <property name="hibernate.connection.datasource">jdbc/datasource</property>
    <property name="hibernate.current_session_context_class">jta</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
    <property name="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.SunOneJtaPlatform</property>
    
    使用CMT(容器管理事务),您不需要声明类似于tx=session.beginTransaction()的任何内容;您让容器为您完成工作。您将仅指定容器何时以及是否支持事务。查看oracle文档

    假设您有一个EJB,它的默认事务范围是必需的。因此hibernate实际上将绑定到该事务范围

    下面是第一个没有事务的ejb使用cmt调用另一个ejb的示例:

    @TransactionAttribute(NOT_SUPPORTED)
    @Stateful
    public class TransactionBean implements TransactionInterface{
    
       @EJB BusinessBean businessBean;
    
       public method1(){
           businessBean.doSomething();
       }
    }
    
    @TransactionAttribute(REQUIRED)
    @Stateful
    public class BusinessBean implements BusinessInterface{
    
        @PersistenceContext(unitName = "some-persistence-unit")
        private EntityManager entityManager;
    
        public void doSomething(){
            Someclass entity = entityManager.finde(Someclass.class, 1) // Find entity with id 1
            entity.setData("somedata");
        }
    }
    
    当methode doSomething()完成时,容器将刷新并将更新提交到数据库,因为外部ejb没有正在运行的事务。只有当数据源也由容器提供时,这才起作用。会话(在JPA
    持久化上下文中,与
    EntityManager
    实例绑定)是数据库模式子集状态的“内存中”快照。 根据您的配置,会话的范围将有所不同。在标准web应用程序中,每个请求将有一个会话

    您可以同时拥有多个状态不同的会话实例,会话彼此隔离(在一个会话上执行的操作在另一个会话中不可见)

    事务是一个工作单元(理论上也是一个会话)。它绑定到底层RDBMS事务系统,并绑定到它打开的会话

    在“容器管理实体管理器”上下文(您称之为CMT)中,容器将负责将会话绑定到定义的范围,并根据遇到的
    @Transactional
    注释以及方法调用传播事务

    实际上发生了什么: 您的容器在某处维护会话实例,并且能够使用
    @PersistenceContext
    注释将其提供给ejb实例。 您正在使用
    sessionFactory.openSession()
    手动构建新的会话实例,在其上打开事务并执行操作。在提交事务、手动刷新或关闭自定义会话并手动触发容器上的刷新之前,托管会话实例无法看到这些修改

    getCurrentSession()
    方法是一种特定于hibernate的机制,在JavaSE上下文(无容器)中充当容器会话范围管理机制。我想(但我不知道hibernate JPA实现)它不会返回容器管理的会话,但在这一点上我可能错了。(编辑我是)

    这里一个合适的解决方案是使用
    @PersistenceContext
    检索当前容器管理的会话实例,并使用
    @Transactional
    注释管理事务传播

    见下文Luk anwser

    仅供参考

    编辑(根据问题版)

    事实上,我似乎完全错了,您不需要使用容器中的持久性上下文注入,但必须使用JTA事务

    根据EJB3.0规范,第13.3.4节使用容器管理事务划分的企业bean:

    The enterprise bean’s business methods [...] must not attempt to obtain or use the javax.transaction.UserTransaction interface.
    
    这意味着你可以使用

    sessionFactory.getCurrentSession() 
    
    但是您不能使用tx=session.beginTransaction(),而是

    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    

    请参阅上面jboss文档中的“使用EJB/CMT划分事务”一节,我从您的问题中学到了一些新的东西,因为我不知道Hibernate可以这样配置(尽管很明显它支持JTA)。无论如何,根据文档,您似乎没有被迫配置它以使用JTA,正如所述:

    如果持久层在应用服务器中运行(例如, 在EJB会话bean之后),通过 Hibernate将自动成为全局JTA事务的一部分。 您还可以安装一个独立的JTA实现并使用它 没有EJB。Hibernate为JTA集成提供了两种策略


    另请参见文档中的示例,因为您不需要在CMT上下文中打开任何事务。但是,如果您想控制事务划分,请查看这些BMT示例。

    正如Luk所指出的,这不是在CMT环境中对其进行编码的方法。无论如何,
    session.beginTransaction()
    部分在这里是安全的,根据 上面说

    如果需要新的基础事务,请开始该事务。否则,在现有基础事务的上下文中继续新的工作

    tx.rollback()
    也是安全的。文档中没有说明,但CMTTransaction实际上执行
    getTransaction().set
    
    sessionFactory.getCurrentSession() 
    
    @TransactionAttribute(TransactionAttributeType.REQUIRED)