使用Apache Tomcat回滚后如何重新打开Hibernate会话

时间:2018-09-24 15:48:27

标签: java hibernate tomcat

我对Hibernate和Apache Tomcat有一个一般性的问题。假设我们有一个带有表单和提交按钮的网页。用户可以输入一些数据,然后将其存储在数据库中。

这是我的配置:

hibernate.cfg.xml

    <property name="connection.datasource">java:/comp/env/jdbc/mia</property>
    <property name="hibernate.connection.driver_class">org.mariadb.jdbc.Driver</property>
    <property name="hibernate.connection.url">${db.url}</property>
    <property name="hibernate.connection.username">${db.user}</property>
    <property name="hibernate.connection.password">${db.password}</property>
    <property name="hibernate.connection.pool_size">10</property>
    <property name="hibernate.generate_statistics">false</property>
    <property name="show_sql">false</property>
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.jdbc.time_zone">UTC</property>

我的交易用途类:

    public class TransactionManager implements ITransactionManager {

    private static final Logger LOGGER =  LoggerFactory.getLogger(TransactionManager.class.getCanonicalName());
       Transaction tx = null;
    boolean isInternalTransaction = false;
    private Session session;

    /* (non-Javadoc)
     * @see IOperationManager#beginOperation
     */
    @Override
    public Session beginOperation() {
        return beginOperation(0);
    }

    /**
     * Try to handle invalidated/inactive sessions
     * @param level recursion limit
     * @return hibernate session
     */
    private Session beginOperation(int level) {
        if (level > 1) {
            throw new HibernateException("Cannot create hibernate session.");
        }
        else {
            session = HibernateUtil.getSessionFactory().getCurrentSession();
            LOGGER.trace("Session.open = {}.", session.isOpen());
            if (session.getTransaction().isActive()) {
                isInternalTransaction = false;
                tx = session.getTransaction();
            } else {
                isInternalTransaction = true;
                tx = session.beginTransaction();
            }
            if (tx == null) {
                session.disconnect();
                return beginOperation(++level);
            }
            return session;
        }
    }

    /* (non-Javadoc)
     * @see IOperationManager#commitOperation
     */
    @Override
    public void commitOperation() {
        if (isInternalTransaction && tx != null && tx.isActive())
            tx.commit();
    }

    /* (non-Javadoc)
     * @see IOperationManager#rollbackOperation
     */
    @Override
    public void rollbackOperation() {
         if (isInternalTransaction && tx != null){
              tx.rollback();
    }

    public boolean isComitted() {
        return !tx.getStatus().isOneOf(TransactionStatus.ACTIVE);
    }
    }

在请求中保存日期

   public void processRequest(){
    TransactionManager txmgr = new TransactionManager();
    try {
        Session session = txmgr.beginOperation();
        // [...] do the saving
        txmgr.commitOperation();
    } catch (PersistenceException ex){
        txmgr.rollbackOperation();
    }
}

如我的配置所示,Hibernate会话使用线程上下文,我认为该上下文将会话绑定到Tomcat线程。这导致以下问题:

回滚事务时,基础会话将被破坏(由于Hibernate内部原因)。现在,此线程处理的以下每个请求均会失败,并显示如下错误: org.hibernate.HibernateException:调用方法'getCriteriaBuilder'在没有活动事务的情况下无效(当前状态:MARKED_ROLLBACK)

休眠文档指出,回滚时必须关闭该会话,并且必须生成一个新会话。但是,如何与Apache Tomcat结合使用呢?据我了解,每个Tomcat线程都会自动分配一个休眠会话。我该如何告诉Tomcat获得新的?还是我必须手动处理?

有人有想法或其他信息可以帮助我解决问题吗?

更新:看起来回滚不是此错误的原因。至少我能够触发回滚并在以后使用该会话。我想我忘了提交/回滚事务。这导致超时,可能导致我的问题。

0 个答案:

没有答案