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