I get this exception when I call the DAO method that uses SessionFactory.getCurrentSession() . The DAO class is annotated using @Transactional , and I also have <tx:annotation-driven/> declared in the application context configuration file.
I can name my DAO methods that execute HQL queries, but whenever I call a DAO method that first receives a Hibernate session, I throw this exception:
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)
I have the following application context configuration file:
<?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"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <value>applicationContext.properties</value> </property> </bean> <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> <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> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="hibernateSessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <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> <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> <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>
The general DAO class (from which the DAO used in my program is extended) is as follows:
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; 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; 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(); } protected Session getCurrentSession() { return sessionFactory.getCurrentSession(); } @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; } @Override public int[] batchUpdate(final Collection<T> entityCollection) { return batchInsert(entityCollection); } public void clear() { getCurrentSession().clear(); } @Override public void delete(final T persistentObject) { getCurrentSession().delete(persistentObject); } @Override public List<T> findAll() { return getCurrentSession().createQuery("from " + persistentClass.getName()).list(); } 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(); } @Override public T findById(final PK id) { return (T) getCurrentSession().load(persistentClass, id); } public void flush() { getCurrentSession().flush(); } @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); } } public void setPersistentClass(final Class<T> persistentClass) { this.persistentClass = persistentClass; } public void setSessionFactory(final SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }
My application gets the DAO from the application context:
// 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");
And an exception occurs when I try to save an object:
esrlDailyAvgDao.saveOrUpdate(esrlDailyAvg);
The DAO class itself uses the Transactional annotation:
@Transactional public class EsrlDailyAvgDaoHibernateImpl extends GenericDaoHibernateImpl<EsrlDailyAvg, Long> implements EsrlDailyAvgDao
The exception stack trace is as follows:
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)