Как открыть Hibernate Session после отката с помощью Apache Tomcat - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть общий вопрос относительно 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>

My Transaction Util Class:

    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 Session использует контекст потока, который, я думаю, связывает сеанс с потоками Tomcat.Это приводит к следующей проблеме:

При откате транзакции базовый сеанс будет поврежден (из-за внутреннего содержимого Hibernate).Теперь каждый следующий запрос, обрабатываемый этим потоком, завершается с ошибкой, подобной этой: org.hibernate.HibernateException: вызов метода 'getCriteriaBuilder' недопустим без активной транзакции (Текущее состояние: MARKED_ROLLBACK)

Документация Hibernate гласит, что при откате сеанс должен быть закрыт и должен быть создан новый.Но как мне это сделать в сочетании с Apache Tomcat?Насколько я понял, каждому потоку Tomcat автоматически назначается сеанс гибернации.Как я могу сказать Tomcat, чтобы получить новый?Или я должен справиться с этим вручную?

У кого-нибудь есть идея или дополнительная информация, которая поможет мне решить мою проблему?

ОБНОВЛЕНИЕ: Похоже, что откат не является причиной этой ошибки.По крайней мере, я был в состоянии вызвать откаты и использовать сеанс впоследствии.Я полагаю, что я забыл зафиксировать / откатить транзакцию.Это приводит к тайм-ауту, который может вызвать мои проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...