我需要确保许多并发用户能够访问数据库。虽然在每次提交后我都关闭了会话,但是有时我的代码遇到以下错误,但是当我几次执行相同的操作时,它会超过错误并可以正常工作。
我的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();
HibernateUtil
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>
在您的“我的代码”代码段中,可能存在一些问题:
finally
session.close()
HibernateUtils.closeSession()
ThreadLocal
catch
rollback
如果之后的“待办事项”块中有异常begin(),则事务保持打开状态,并且ThreadLocal不清除。
begin()
您的代码可能正常工作,但是在高负载下可能会发生(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():记录每次访问,包括线程的名称。最终,同一线程必须进行一次或多次“获取”,然后再进行“关闭”。
HibernateUtil.getSession()
HibernateUtil.closeSession()
在您的情况下,我什至会考虑只有一个“ get”,并且只要您的线程正在执行其工作单元,就传递该会话:这样一来,发现问题可能会更容易。
关于SO的另一个问题报告了类似的问题:Hibernate4.1.9(最新的最终构建)报告了不支持嵌套事务。
您可以在commit()检查之后添加一些代码,以确认交易是否真的完成了(通过调用wasCommitted())。
commit()
wasCommitted()
Javadoc中的引文wasCommitted():
即使成功调用commit(),此方法也可能返回false。例如,如果基于JTA的策略没有启动事务,则它们对no(op)的调用不执行操作。在这种情况下,他们还报告wasCommitted()为假。