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

djm*_*jmj 6 hibernate ejb jpa transactions java-ee

当在CMT(EJB3)中使用以下编程事务和会话习惯用法并且Hibernate Core设置为使用CMT时会发生什么?
假设当前CMT事务是必需的并且使用默认值启动@TransactionAttribute(REQUIRED)

  1. hibernate事务是否会加入当前的CMT beginTransaction()
  2. commit()尝试立即提交hibernate事务还是等到当前的CMT提交?
  3. 在CMT关闭会话时会发生什么?

B.行为是否取决于当前会话是否与CMT绑定使用getCurrentSession()

// A: openSession()
// B: getCurrentSession();
Session session = sessionFactory.openSession(); 
Transaction tx = null;
try
{
    tx = session.beginTransaction();

    // do some work

    tx.commit();
}
catch (final RuntimeException e)
{
    try 
    {
        tx.rollback();
    }
    catch (final RuntimeException e)
    {
        // log error
    }
    throw e;
}
finally
{
    session.close();
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,我目前正在使用单个数据库,并且使用Hibernate的程序化JDBC事务工作正常.现在,该应用程序还使用JMS-Queue for Mail消息传递,并希望将其合并到全局CMT事务中.

编辑:

目前我根本不在应用程序中使用EntityManager,并且还希望将代码可移植到非托管环境中.

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

Hibernate 4.2.6和Glassfish 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>
Run Code Online (Sandbox Code Playgroud)

SessionFactory检索

SessionFactory是在单例EJB中构建的.剥掉不必要的东西.

@Startup
@Singleton
public class SessionManager
{
    private SessionFactory sessionFactory;

    public SessionManager()
    {
        final Configuration configuration = new Configuration().configure();
        this.sessionFactory = configuration.buildSessionFactory();
    }
}
Run Code Online (Sandbox Code Playgroud)

Dru*_*nix 1

正如 Luk 所指出的,这不是在 CMT 环境中编码的方法。无论如何, session.beginTransaction()根据 http://docs.jboss.org/hibernate/annotations/3.5/api/org/hibernate/Session.html#beginTransaction%28%29,该部分在这里是安全的

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

tx.rollback()也很安全。文档中没有说明,但 CMTTransaction 实际上执行getTransaction().setRollbackOnly(),即它只是将 TX 标记为回滚。提交实际上不会提交 TX,但可能会刷新会话。如果涉及多个资源,则真正的提交将违反事务语义。