usar transacción transacciones tran procedimientos explícitas ejemplos ejemplo datos como begin anidada almacenados hibernate java-ee transactions

hibernate - transacción - ¿Cómo evitar transacciones anidadas no soportadas error?



transacciones sql server (4)

En tu fragmento de código "Mi código", puede haber algunos problemas:

  1. En caso de una excepción, no hay un bloque final para cerrar la sesión
  2. Está llamando a session.close() , pero esto es diferente de HibernateUtils.closeSession() . Así que el ThreadLocal no se borra.
  3. No hay bloque de catch para excepciones; como consecuencia no hay rollback .
  4. ¿Vuelve a hacer excepciones o son ignoradas (en silencio)?

Si hay una excepción en el bloque "para hacer" después de begin() , la transacción permanece abierta y ThreadLocal no se borra.

Su código puede funcionar bien normalmente, pero bajo una carga alta puede haber tiempos de espera (bloqueo de SQL), etc., y en este caso, de vez en cuando, se lanzará una excepción.

Así que revise cada fragmento de código para el correcto manejo de excepciones:

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(); }

Puede agregar algún código de "contabilidad" a HibernateUtil.getSession() y HibernateUtil.closeSession() : Registre cada acceso, incluido el nombre del hilo. Finalmente, uno o varios "get" por el mismo hilo deben ir seguidos de un "close".

En su caso, incluso consideraría tener un solo "get", y transmitir la sesión siempre y cuando su hilo esté haciendo su unidad de trabajo: de esta manera posiblemente sea más fácil encontrar el problema.

Hay otra pregunta en SO que informa un problema similar: Hibernate 4.1.9 (última compilación final) que informa sobre transacciones anidadas no admitidas .

Puede agregar algo de código después de commit() para verificar, si la transacción se ha completado realmente (llamando a wasCommitted() ).

Una cita del Javadoc de wasCommitted() :

Este método podría devolver falso incluso después de una invocación exitosa de commit (). Como ejemplo, las estrategias basadas en JTA no-op en las llamadas commit () si no iniciaron la transacción; en ese caso, también informaron que wasCommitted () como falso.

Necesito asegurarme de que muchos usuarios simultáneos puedan acceder a la base de datos. Aunque después de cada confirmación, cierro la sesión, pero a veces mi código se ejecuta en el siguiente error, pero cuando hago la misma operación varias veces, supera el error y funciona.

Mi hibernación es 4.2.1.Final

Messages: nested transactions not supported File: org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java Line number: 152

Mi código

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(); } } }

Configuración

<?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>


Estaba enfrentando el mismo problema, resolví mi problema poniendo tr.commit (); función después de cada transacción. Ocurre solo cuando inicia una transacción sin cerrar la transacción anterior.

session = HibernateUtil.getSession(); session.getTransaction().begin(); OR session.beginTransaction(); ... to do .... session.getTransaction().commit(); session.close(); OR HibernateUtil.closeSession();

Parece que también estás haciendo el mismo error.


Probablemente haya iniciado una transacción e intente iniciar otra sin haber confirmado o revertido la anterior. La expresión idiomática cuando se usa la demarcación de transacción programática es la siguiente:

Transaction transaction = null; try { session = HibernateUtil.getSession(); transaction = session.beginTransaction(); ... to do .... transaction.commit(); } catch (RuntimeException e) { transaction.rollback(); throw e; }

Agregue la siguiente propiedad en su Hibernate.cfg.xml

<prop key="hibernate.current_session_context_class">thread</prop>


Use session.beginTransaction () en lugar de session.getTransaction (). Begin () en su código. Debe comenzar una nueva unidad de trabajo, por lo que beginTransaction comenzará una nueva transacción. Entonces tu código se verá como:

session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); ... to do .... transaction.commit();

Haga clic Here para obtener más información sobre beginTransaction (); método.

Creo que eso resolverá tu problema. Por favor, hágamelo saber si el problema persiste.