如何避免嵌套事务不支持的错误?

我需要确保许多并发用户能够访问数据库。虽然在每次提交后我都关闭了会话,但是有时我的代码遇到以下错误,但是当我几次执行相同的操作时,它会超过错误并可以正常工作。

我的hibernate状态是4.2.1。

Messages:   

nested transactions not supported

File: org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java

Line number: 152

session = HibernateUtil.getSession();

session.getTransaction().begin(); OR session.beginTransaction();

... to do ....

session.getTransaction().commit();

session.close(); OR HibernateUtil.closeSession();

import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {

private static ServiceRegistry serviceRegistry;

private static final ThreadLocal<Session> threadLocal = new ThreadLocal();

private static SessionFactory sessionFactory;

private static SessionFactory configureSessionFactory() {

try {

Configuration configuration = new Configuration();

configuration.configure();

serviceRegistry = new ServiceRegistryBuilder()

.applySettings(configuration.getProperties())

.buildServiceRegistry();

sessionFactory = configuration.buildSessionFactory(serviceRegistry);

return sessionFactory;

} catch (HibernateException e) {

System.out.append("** Exception in SessionFactory **");

e.printStackTrace();

}

return sessionFactory;

}

static {

try {

sessionFactory = configureSessionFactory();

} catch (Exception e) {

System.err.println("%%%% Error Creating SessionFactory %%%%");

e.printStackTrace();

}

}

private HibernateUtil() {

}

public static SessionFactory getSessionFactory() {

return sessionFactory;

}

public static Session getSession() throws HibernateException {

Session session = threadLocal.get();

if (session == null || !session.isOpen()) {

if (sessionFactory == null) {

rebuildSessionFactory();

}

session = (sessionFactory != null) ? sessionFactory.openSession() : null;

threadLocal.set(session);

}

return session;

}

public static void rebuildSessionFactory() {

try {

sessionFactory = configureSessionFactory();

} catch (Exception e) {

System.err.println("%%%% Error Creating SessionFactory %%%%");

e.printStackTrace();

}

}

public static void closeSession() throws HibernateException {

Session session = (Session) threadLocal.get();

threadLocal.set(null);

if (session != null) {

session.close();

}

}

}

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->

<property name="connection.driver_class">

com.mysql.jdbc.Driver

</property>

<property name="connection.url">

jdbc:mysql://localhost:3306/MyProject

</property>

<property name="connection.username">root</property>

<property name="connection.password"></property>

<!-- JDBC connection pool (use the built-in) -->

<property name="connection.pool_size">12</property>

<!-- SQL dialect -->

<property name="dialect">

org.hibernate.dialect.MySQLDialect

</property>

<!-- Enable Hibernate's automatic session context management -->

<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->

<property name="cache.provider_class">

org.hibernate.cache.NoCacheProvider

</property>

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<mapping class="com.project.common.Project" />

<mapping class="com.project.common.School" />

<mapping class="com.project.common.Address" />

<mapping class="com.project.common.Female" />

<mapping class="com.project.common.Male" />

<mapping class="com.project.common.Credential" />

<mapping class="com.project.common.Users" />

</session-factory>

</hibernate-configuration>

回答:

在您的“我的代码”代码段中,可能存在一些问题:

  1. 发生异常时,没有finally阻止关闭会话的块
  2. 您正在打电话session.close(),但这与有所不同HibernateUtils.closeSession()。因此,ThreadLocal不会清除。
  3. 没有catch例外。结果是没有rollback
  4. 您是抛出异常还是被(静默)忽略?

如果之后的“待办事项”块中有异常begin(),则事务保持打开状态,并且ThreadLocal不清除。

您的代码可能正常工作,但是在高负载下可能会发生(SQL锁定)超时等情况,在这种情况下,偶尔会抛出异常。

因此,请检查 每个 代码段以进行 正确的 异常处理:

final Session session = HibernateUtil.getSession();

try {

final Transaction transaction = session.beginTransaction();

try {

// The real work is here

transaction.commit();

} catch (Exception ex) {

// Log the exception here

transaction.rollback();

throw ex;

}

} finally {

HibernatilUtil.closeSession();

}


您可以向HibernateUtil.getSession()和添加一些“簿记”代码HibernateUtil.closeSession():记录每次访问,包括线程的名称。最终,同一线程必须进行一次或多次“获取”,然后再进行“关闭”。

在您的情况下,我什至会考虑只有一个“ get”,并且只要您的线程正在执行其工作单元,就传递该会话:这样一来,发现问题可能会更容易。


关于SO的另一个问题报告了类似的问题:Hibernate4.1.9(最新的最终构建)报告了不支持嵌套事务。

您可以在commit()检查之后添加一些代码,以确认交易是否真的完成了(通过调用wasCommitted())。

Javadoc中的引文wasCommitted()

即使成功调用commit(),此方法也可能返回false。例如,如果基于JTA的策略没有启动事务,则它们对no(op)的调用不执行操作。在这种情况下,他们还报告wasCommitted()为假。

以上是 如何避免嵌套事务不支持的错误? 的全部内容, 来源链接: utcz.com/qa/403148.html

回到顶部