transacciones transaccional son requires_new que las globales false java hibernate spring

java - son - transaccional spring boot



Ninguna sesión de Hibernate está vinculada al hilo, y la configuración no permite la creación de una no transaccional aquí (8)

Obtengo esta excepción cuando llamo a un método DAO que usa SessionFactory.getCurrentSession() . La clase DAO está anotada con @Transactional y también tengo <tx:annotation-driven/> declarado en el archivo de configuración de contexto de la aplicación.

Puedo llamar a mis métodos DAO que realizan consultas HQL, pero cada vez que llamo a un método DAO que primero obtiene la sesión de Hibernate, entonces me encuentro con esta excepción:

SEVERE: Failed to save the object. org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622) at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.getCurrentSession(GenericDaoHibernateImpl.java:56) at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.saveOrUpdate(GenericDaoHibernateImpl.java:187)

Tengo el siguiente archivo de configuración de contexto de la aplicación:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:flex="http://www.springframework.org/schema/flex" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- load values used for bean properties --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <value>applicationContext.properties</value> </property> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- DataSource where objects will be persisted --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="${datasource.username}" /> <property name="password" value="${datasource.password}" /> <property name="url" value="${datasource.url}" /> <property name="driverClassName" value="${datasource.driver}" /> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- Factory bean for Hibernate Sessions --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg</value> <value>gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations</value> <value>gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.use_sql_comments">true</prop> <prop key="hibernate.jdbc.batch_size">50</prop> <prop key="hibernate.query.substitutions">true 1, false 0</prop> <prop key="hibernate.max_fetch_depth">6</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddlauto}</prop> <prop key="hibernate.cache.use_second_level_cache">${hibernate.use_second_level_cache}</prop> </props> </property> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- Transaction Manager bean --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="hibernateSessionFactory" /> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- enable the configuration of transactional behavior based on annotations --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- DAO for ESRL Station objects --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="esrlStationDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlStationDaoHibernateImpl"> <property name="sessionFactory" ref="hibernateSessionFactory" /> <property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation" /> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- DAO for ESRL Observations objects --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="esrlObservationsDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlObservationsDaoHibernateImpl"> <property name="sessionFactory" ref="hibernateSessionFactory" /> <property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations" /> </bean> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- DAO for ESRL daily average objects --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <bean id="esrlDailyAvgDao" class="gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlDailyAvgDaoHibernateImpl"> <property name="sessionFactory" ref="hibernateSessionFactory" /> <property name="persistentClass" value="gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg" /> </bean> </beans>

La clase DAO genérica (a partir de la cual se amplía el DAO que se está utilizando en mi programa) se ve así:

package gov.noaa.ncdc.cmb.persistence.dao; import gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity; import java.io.Serializable; import java.util.Collection; import java.util.Date; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Example; /** * This class is an implementation of GenericDao<T, PK> using Hibernate. */ public class GenericDaoHibernateImpl<T extends PersistentEntity<PK>, PK extends Serializable> implements GenericDao<T, PK> { private SessionFactory sessionFactory; static private Log log = LogFactory.getLog(GenericDaoHibernateImpl.class); private Class<T> persistentClass; /** * Can be used within subclasses as a convenience method. * * @param criterionList the criteria to find by * @return the list of elements that match the specified criteria */ protected List<T> findByCriteria(final List<Criterion> criterionList) { Criteria criteria = getCurrentSession().createCriteria(persistentClass); for (Criterion criterion : criterionList) { criteria.add(criterion); } return criteria.list(); } protected String getCanonicalPersistentClassName() { return persistentClass.getCanonicalName(); } /** * Gets the current Hibernate Session object. * * @return */ protected Session getCurrentSession() { return sessionFactory.getCurrentSession(); } /* * This method only provided for interface compatibility. Not recommended for use with large batches * (this is an inefficient implementation, and it''s somewhat difficult to perform batch operations with Hibernate). * * (non-Javadoc) * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#batchInsert(java.util.Collection) */ @Override public int[] batchInsert(final Collection<T> entityCollection) { int[] updateCounts = new int[entityCollection.size()]; int i = 0; for (T entity : entityCollection) { try { saveOrUpdate(entity); updateCounts[i] = 1; i++; } catch (Exception ex) { clear(); throw new RuntimeException(ex); } } flush(); clear(); return updateCounts; } /* * This method only provided for interface compatibility. Not recommended for use with large batches * (this is an inefficient implementation, and it''s somewhat difficult to perform batch operations with Hibernate). * * (non-Javadoc) * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#batchUpdate(java.util.Collection) */ @Override public int[] batchUpdate(final Collection<T> entityCollection) { return batchInsert(entityCollection); } /** * Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do * not close open iterators or instances of ScrollableResults. */ public void clear() { getCurrentSession().clear(); } /* * (non-Javadoc) * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#delete(gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity) */ @Override public void delete(final T persistentObject) { getCurrentSession().delete(persistentObject); } /* * (non-Javadoc) * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#findAll() */ @Override public List<T> findAll() { return getCurrentSession().createQuery("from " + persistentClass.getName()).list(); } /** * Finds a collection of entity objects which match to the example instance, minus any specified properties which should be excluded from the matching. * * @param exampleInstance * @param excludeProperty * @return */ public List<T> findByExample(final T exampleInstance, final String[] excludeProperty) { Criteria criteria = getCurrentSession().createCriteria(persistentClass); Example example = Example.create(exampleInstance); if (excludeProperty != null) { for (String exclude : excludeProperty) { example.excludeProperty(exclude); } } criteria.add(example); return criteria.list(); } /* * (non-Javadoc) * @see com.sun.cloud.lifecycle.core.persistence.dao.GenericDao#findById(java.io.Serializable) */ @Override public T findById(final PK id) { return (T) getCurrentSession().load(persistentClass, id); } /** * Force this session to flush. Must be called at the end of a unit of work, before commiting the transaction and * closing the session (depending on flush-mode, Transaction.commit() calls this method). * * Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory. */ public void flush() { getCurrentSession().flush(); } /* * (non-Javadoc) * @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#saveOrUpdate(gov.noaa.ncdc.cmb.persistence.entity.PersistentEntity) */ @Override public T saveOrUpdate(final T entity) { try { entity.setUpdatedDate(new Date()); getCurrentSession().saveOrUpdate(entity); return entity; } catch (Exception ex) { String errorMessage = "Failed to save the object."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } } /** * Setter for the persistentClass property. * * @param persistentClass */ public void setPersistentClass(final Class<T> persistentClass) { this.persistentClass = persistentClass; } /** * Property setter. * * @param sessionFactory */ public void setSessionFactory(final SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }

Mi aplicación obtiene el DAO desde el contexto de la aplicación:

// load the Spring application context, get the DAOs ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] { "dailyAveragingApplicationContext.xml" }); esrlDailyAvgDao = (EsrlDailyAvgDao) applicationContext.getBean("esrlDailyAvgDao"); esrlObservationsDao = (EsrlObservationsDao) applicationContext.getBean("esrlObservationsDao");

Y la excepción se encuentra cuando intento guardar una entidad:

esrlDailyAvgDao.saveOrUpdate(esrlDailyAvg);

La clase DAO en sí usa la anotación transaccional:

@Transactional public class EsrlDailyAvgDaoHibernateImpl extends GenericDaoHibernateImpl<EsrlDailyAvg, Long> implements EsrlDailyAvgDao

El seguimiento de pila de excepción se ve así:

SEVERE: Failed to save the object. org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622) at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.getCurrentSession(GenericDaoHibernateImpl.java:56) at gov.noaa.ncdc.cmb.persistence.dao.GenericDaoHibernateImpl.saveOrUpdate(GenericDaoHibernateImpl.java:187) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196) at $Proxy19.saveOrUpdate(Unknown Source) at gov.noaa.ncdc.cmb.esrl.ingest.EsrlDailyAvgProcessor.main(EsrlDailyAvgProcessor.java:469)


¡Faltan <context:annotation-config /> de su contexto de primavera para que las anotaciones no se escaneen!


¿Tiene org.springframework.orm.hibernate3.support.OpenSessionInViewFilter configurado en org.springframework.orm.hibernate3.support.OpenSessionInViewFilter ''s web.xml (suponiendo que su aplicación es una aplicación web), o envolver las llamadas en consecuencia?


Hoy tuve el mismo problema. Mientras busco una solución aquí, cometí el error tonto de no importar

import org.springframework.transaction.annotation.Transactional;

sin saberlo, he importado

import javax.transaction.Transactional;

Después de cambiarlo todo funcionó bien.

Así que pensé en compartir, si alguien hace el mismo error.


Puede tener el @Transactional en la clase secundaria, pero debe anular cada uno de los métodos y llamar al método súper para que funcione.

Ejemplo:

@Transactional(readOnly = true) public class Bob<SomeClass> { @Override public SomeClass getValue() { return super.getValue(); } }

Esto le permite configurarlo para cada uno de los métodos necesarios.


Siempre que se enfrente al siguiente error simplemente sígalo.

org.hibernate.HibernateException: ninguna sesión de Hibernate vinculada a thread, y la configuración no permite la creación de una no transaccional aquí en org.springframework.orm.hibernate3.SpringSessionContext.currentSession (SpringSessionContext.java:63)

Coloque una anotación @Transactional para cada método de implementación de clases.


Tuve el siguiente error:

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)

Lo arreglé cambiando mi archivo de propiedades de hibernación

hibernate.current_session_context_class=thread

Mi código y archivo de configuración de la siguiente manera

session = getHibernateTemplate().getSessionFactory().getCurrentSession(); session.beginTransaction(); session.createQuery(Qry).executeUpdate(); session.getTransaction().commit();

en el archivo de propiedades

hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.query_factory_class=org.hibernate.hql.ast.ASTQueryTranslatorFactory hibernate.current_session_context_class=thread

en el archivo de cofiguración

<properties> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.query.factory_class">${hibernate.query_factory_class}</prop> <prop key="hibernate.generate_statistics">true</prop> <prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop> </props> </property> </properties>

Gracias,
Ashok


después de agregar la propiedad:

<prop key="hibernate.current_session_context_class">thread</prop> Obtengo la excepción como:

org.hibernate.HibernateException: createQuery is not valid without active transaction org.hibernate.HibernateException: save is not valid without active transaction.

entonces creo que establecer esa propiedad no es una buena solución.

finalmente resuelvo el problema "Ninguna sesión de Hibernate vinculada al hilo":

1. <!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
2.add <tx:annotation-driven /> a servlet-context.xml o dispatcher-servlet.xml
3.add @Transactional después de @Service y @Repository


@Transactional esto agregando @Transactional a la clase de implementación HIO de Hibernate / base (la clase padre que implementa el método saveOrUpdate () heredado por el DAO que uso en el programa principal), es decir, el @Transactional necesita ser especificado en el real clase que implementa el método. Mi suposición era, en cambio, que si declaraba @Transactional en la clase hija, entonces incluía todos los métodos heredados por la clase hija. Sin embargo, parece que la anotación @Transactional solo se aplica a los métodos implementados dentro de una clase y no a los métodos heredados por una clase.