我对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获得新的?还是我必须手动处理?
有人有想法或其他信息可以帮助我解决问题吗?
更新:看起来回滚不是此错误的原因。至少我能够触发回滚并在以后使用该会话。我想我忘了提交/回滚事务。这导致超时,可能导致我的问题。