没有将Hibernate Session绑定到线程,并且配置不允许在此处创建非事务性的Session。

3 浏览
0 Comments

没有将Hibernate Session绑定到线程,并且配置不允许在此处创建非事务性的Session。

在调用使用SessionFactory.getCurrentSession()的DAO方法时,我遇到了这个异常。DAO类使用了@Transactional注解,并且在应用程序上下文配置文件中声明了

我可以调用执行HQL查询的DAO方法,但是每当我调用首先获取Hibernate会话然后运行进入此异常的DAO方法时,就会遇到这个异常:

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)

我有以下的应用程序上下文配置文件:



    
    
    
    
        
            applicationContext.properties
        
    
    
    
    
    
        
        
        
        
    
    
    
    
    
        
        
            
                gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg
                gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations
                gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation
            
        
        
            
                ${hibernate.dialect}
                false
                true
                true
                50
                true 1, false 0
                6
                ${hibernate.hbm2ddlauto}
                ${hibernate.use_second_level_cache}
            
        
    
    
    
    
    
        
    
    
    
    
    
    
    
    
    
        
        
    
    
    
    
    
        
        
    
    
    
    
    
        
        
    
 

通用DAO类(程序中使用的DAO是从该类继承而来)的代码如下:

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 using Hibernate.
 */
public class GenericDaoHibernateImpl, PK extends Serializable>
    implements GenericDao
{
    private SessionFactory sessionFactory;
    static private Log log = LogFactory.getLog(GenericDaoHibernateImpl.class);
    private Class 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 findByCriteria(final List 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 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 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 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 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 persistentClass)
    {
        this.persistentClass = persistentClass;
    }
    /**
     * Property setter.
     * 
     * @param sessionFactory
     */
    public void setSessionFactory(final SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }
}

我的应用程序从应用程序上下文中获取DAO:

// 加载Spring应用程序上下文,获取DAO
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] { "dailyAveragingApplicationContext.xml" });
esrlDailyAvgDao = (EsrlDailyAvgDao) applicationContext.getBean("esrlDailyAvgDao");
esrlObservationsDao = (EsrlObservationsDao) applicationContext.getBean("esrlObservationsDao");

当我尝试保存一个实体时,遇到了异常:

esrlDailyAvgDao.saveOrUpdate(esrlDailyAvg);

DAO类本身使用了Transactional注解:

@Transactional
public class EsrlDailyAvgDaoHibernateImpl
    extends GenericDaoHibernateImpl
    implements EsrlDailyAvgDao

异常堆栈跟踪如下:

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)

0