没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的 [英] No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

查看:114
本文介绍了没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我调用一个使用 SessionFactory.getCurrentSession()的DAO方法时,我得到这个异常。 DAO类用 @Transactional 注释,我还有< tx:annotation-driven /> 声明应用程序上下文配置文件。

我可以调用执行HQL查询的DAO方法,但每当我调用一个首先获取Hibernate会话的DAO方法时,我都会遇到这个问题例外:

  SEVERE:保存对象失败。 
org.hibernate.HibernateException:没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的$ b $ 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)

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

 <?xml version =1.0encoding = 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属性的加载值 - >
<! - ~~~~~~~~~~~~~~~~~~~~~~& - > ;
< bean class =org.springframework.beans.factory.config.PropertyPlaceholderConfigurer>
< property name =locations>
< value> applicationContext.properties< / value>
< / property>
< / bean>


<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~>>
<! - 其中对象将被持久保存的数据源 - >
<! - 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 ~~~ - >
< bean id =dataSourceclass =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =usernamevalue =$ {datasource.username}/>
< property name =passwordvalue =$ {datasource.password}/>
< property name =urlvalue =$ {datasource.url}/>
< property name =driverClassNamevalue =$ {datasource.driver}/>
< / bean>


<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~ - >
<! - 用于休眠会话的工厂bean - >
<! - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>>
< bean id =hibernateSessionFactoryclass =org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =annotatedClasses>
< list>
<值> gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg< /值>
<值> gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations< /值>
<值> gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation< /值>
< / list>
< / property>
< property name =hibernateProperties>
<道具>
< 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>
< /道具>
< / property>
< / bean>


<! - - ~~~~~~~~~~~~~~~~~~~~~~~ - >
<! - 事务管理器bean - >
<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - >
< bean id =transactionManagerclass =org.springframework.orm.hibernate3.HibernateTransactionManager>
< property name =sessionFactoryref =hibernateSessionFactory/>
< / bean>


<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 - >
<! - 启用基于注释的事务行为配置 - >
<! - 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 - >
< tx:注解驱动的事务管理器=transactionManager/>


<! - 〜~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - >> ;
<! - DAO用于ESRL工作站对象 - >
<! - 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 - >
< bean id =esrlStationDaoclass =gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlStationDaoHibernateImpl>
< property name =sessionFactoryref =hibernateSessionFactory/>
< property name =persistentClassvalue =gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlStation/>
< / bean>


<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~ - >
<! - DAO for ESRL Observations objects - >
<! - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>>
< bean id =esrlObservationsDaoclass =gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlObservationsDaoHibernateImpl>
< property name =sessionFactoryref =hibernateSessionFactory/>
< property name =persistentClassvalue =gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlObservations/>
< / bean>


<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ - >
<! - DAO用于ESRL日常平均物品 - >
<! - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - >
< bean id =esrlDailyAvgDaoclass =gov.noaa.ncdc.cmb.esrl.domain.dao.EsrlDailyAvgDaoHibernateImpl>
< property name =sessionFactoryref =hibernateSessionFactory/>
< property name =persistentClassvalue =gov.noaa.ncdc.cmb.esrl.domain.entity.EsrlDailyAvg/>
< / bean>


< / beans>

泛型DAO类(从我的程序中使用的DAO扩展)如下所示:

  package gov.noaa.ncdc.cmb.persistence.dao; 

导入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;

/ **
*这个类是GenericDao< T,PK>使用Hibernate。
* /
public class GenericDaoHibernateImpl< T extends PersistentEntity< PK>,PK extends Serializable>
实现GenericDao< T,PK>
{
private SessionFactory sessionFactory;

static private Log log = LogFactory.getLog(GenericDaoHibernateImpl.class);

私人课程< T>对PersistentClass;

/ **
*可以在子类中用作方便的方法。
*
* @param criterionList根据
查找的标准* @返回符合指定条件的元素列表
* /
protected List< T> findByCriteria(final List< Criterion> criterionList)
{
Criteria criteria = getCurrentSession()。createCriteria(persistentClass); (标准标准:标准清单)

{
criteria.add(标准);
}
return criteria.list();


protected String getCanonicalPersistentClassName()
{
return persistentClass.getCanonicalName();
}

/ **
*获取当前的Hibernate Session对象。
*
* @return
* /
protected Session getCurrentSession()
{
return sessionFactory.getCurrentSession();
}

/ *
*此方法仅提供界面兼容性。不建议与大批量
*一起使用(这是一个效率低下的实现,并且使用Hibernate执行批处理操作有点困难)。
*
*(非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; (T entity:entityCollection)

{
try
{
saveOrUpdate(entity);
updateCounts [i] = 1;
i ++;
}
catch(Exception ex)
{
clear();
抛出新的RuntimeException(ex);
}
}
flush();
clear();

返回updateCounts;
}

/ *
*此方法仅提供界面兼容性。不建议与大批量
*一起使用(这是一个效率低下的实现,并且使用Hibernate执行批处理操作有点困难)。
*
*(非Javadoc)
* @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#batchUpdate(java.util.Collection)
* /
@Override
public int [] batchUpdate(final Collection< T> entityCollection)
{
return batchInsert(entityCollection);
}

/ **
*完全清除会话。退出所有加载的实例并取消所有未决的保存,更新和删除。
*不能关闭打开的迭代器或ScrollableResults的实例。
* /
public void clear()
{
getCurrentSession()。clear();
}

/ *
*(非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 (持久性对象);
}

/ *
*(非Javadoc)
* @see gov.noaa.ncdc.cmb.persistence.dao.GenericDao#findAll()
* /
@Override
public List< T> findAll()
{
return getCurrentSession()。createQuery(from+ persistentClass.getName())。list();
}

/ **
*查找与示例实例相匹配的实体对象的集合,减去应从匹配中排除的任何指定属性。
*
* @param exampleInstance
* @param excludeProperty
* @return
* /
public List< T> findByExample(final T exampleInstance,
final String [] excludeProperty)
{
Criteria criteria = getCurrentSession()。createCriteria(persistentClass);
示例示例= Example.create(exampleInstance);
if(excludeProperty!= null)
{
for(String exclude:excludeProperty)
{
example.excludeProperty(exclude);
}
}
criteria.add(example);
return criteria.list();
}

/ *
*(非Javadoc)
*请参阅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);
}

/ **
*强制本次会话刷新。必须在工作单元结束时调用,然后提交事务并
*关闭会话(取决于flush-mode,Transaction.commit()调用此方法)。
*
* Flushing是将持久存储器与持久存储器中的持久存储器进行同步的过程。
* /
public void flush()
{
getCurrentSession()。flush();
}

/ *
*(非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);
返回实体;
}
catch(Exception ex)
{
String errorMessage =无法保存对象。
log.error(errorMessage,ex);
抛出新的RuntimeException(errorMessage,ex);
}
}

/ **
*用于persistentClass属性的Setter。
*
* @param persistentClass
* /
public void setPersistentClass(final Class< T> persistentClass)
{
this.persistentClass = persistentClass;
}

/ **
*属性设定器。
*
* @param sessionFactory
* /
public void setSessionFactory(final SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}

}

我的应用程序从应用程序上下文:

  //加载Spring应用程序上下文,获取DAOs 
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< EsrlDailyAvg,Long>
implements EsrlDailyAvgDao

异常堆栈跟踪如下所示:

  SEVERE:无法保存对象。 
org.hibernate.HibernateException:没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的$ b $ 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。反射.NativeMethodAccessorImpl.invoke(未知源)
在sun.reflect.DelegatingMethodAccessorImpl.invoke(未知源)
在java.lang.reflect.Method.invoke(未知源)
at org。 springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.spri ngframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
at $ Proxy19.saveOrUpdate(Unknown Source)
at gov.noaa.ncdc.cmb.esrl.ingest.EsrlDailyAvgProcessor.main( EsplDailyAvgProcessor.java:469)


解决方案

@Transactional 添加到基本/泛型Hibernate DAO实现类(实现由我在主程序中使用的DAO继承的saveOrUpdate()方法的父类),即<需要在实现该方法的实际类上指定code> @Transactional 。我的假设是,如果我在子类上声明 @Transactional ,那么它包含了子类继承的所有方法。但是,似乎 @Transactional 注释仅适用于在类中实现的方法,而不适用于由类继承的方法。


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)

解决方案

I resolved this by adding @Transactional to the base/generic Hibernate DAO implementation class (the parent class which implements the saveOrUpdate() method inherited by the DAO I use in the main program), i.e. the @Transactional needs to be specified on the actual class which implements the method. My assumption was instead that if I declared @Transactional on the child class then it included all of the methods that were inherited by the child class. However it seems that the @Transactional annotation only applies to methods implemented within a class and not to methods inherited by a class.

这篇关于没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆