I am getting this exception when I call a DAO method which uses SessionFactory.getCurrentSession()
. The DAO class is annotated with @Transactional
and I also have <tx:annotation-driven/>
declared in the application context configuration file.
I can call my DAO methods which perform HQL queries, but whenever I call a DAO method which first gets the Hibernate session then I run into 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">
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- 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>
The generic DAO class (from which the DAO being used in my program is extended) looks like this:
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;
}
}
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 the exception is encountered when I try to save an entity:
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 looks like this:
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)
Whenever you will face below error just follow it.
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)
Put a @Transactional
annotation for each method of implementing classes.
I got the following 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)
I fixed this by changing my hibernate properties file
hibernate.current_session_context_class=thread
My code and configuration file as follows
session = getHibernateTemplate().getSessionFactory().getCurrentSession();
session.beginTransaction();
session.createQuery(Qry).executeUpdate();
session.getTransaction().commit();
on properties file
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
on cofiguration file
<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>
Thanks,
Ashok
You can have the @Transactional in the child class, but you have to override each of the methods and call the super method in order to get it to work.
Example:
@Transactional(readOnly = true)
public class Bob<SomeClass> {
@Override
public SomeClass getValue() {
return super.getValue();
}
}
This allows it to set it up for each of the methods it's needed for.
I had the same issue today.While searching here for solution,I have did silly mistake that is instead of importing
import org.springframework.transaction.annotation.Transactional;
unknowingly i have imported
import javax.transaction.Transactional;
Afer changing it everything worked fine.
So thought of sharing,If somebody does same mistake .
I was getting the same the error inside a shared function, but it was only happening for some calls to this shared function. I eventually realized that one of classes calling the shared function wasn't wrapping it inside of a Unit of Work. Once I updated this classes functions with a Unit of Work everything worked as expected.
So just posting this for any future visitors who run into this same error, but for whom the accepted answer doesn't apply.
Have you got org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
configured in webapp's web.xml
(assuming your application is a webapp), or wrapping calls accordingly?
You are missing <context:annotation-config />
from your spring context so the annotations are not being scanned!
after I add the property:
<prop key="hibernate.current_session_context_class">thread</prop>
I get the exception like:
org.hibernate.HibernateException: createQuery is not valid without active transaction
org.hibernate.HibernateException: save is not valid without active transaction.
so I think setting that property is not a good solution.
finally I solve "No Hibernate Session bound to thread" problem :
1.<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
2.add <tx:annotation-driven />
to servlet-context.xml or dispatcher-servlet.xml
3.add @Transactional after @Service and @Repository
Source: Stackoverflow.com