2011-02-10 10 views
43

SessionFactory.getCurrentSession()を使用するDAOメソッドを呼び出すと、この例外が発生します。 DAOクラスには@Transactionalという注釈が付けられており、アプリケーションコンテキスト設定ファイルには<tx:annotation-driven/>も宣言されています。スレッドにバインドされていないHibernateセッションはありません。コンフィグレーションでは非トランザクション型のセッションを作成できません。

私は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) 

私は、次のアプリケーションコンテキストのコンフィギュレーション・ファイルを持っています:

<?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> 

ジェネリック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<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; 
    } 

} 

私のアプリケーションは、アプリケーションコンテキストからDAOを取得します。

// 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"); 

そして、私は、エンティティを保存しようとすると例外が発生した:

esrlDailyAvgDao.saveOrUpdate(esrlDailyAvg); 

DAOクラス自体は、トランザクション注釈使用しています。

@Transactional 
public class EsrlDailyAvgDaoHibernateImpl 
    extends GenericDaoHibernateImpl<EsrlDailyAvg, Long> 
    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

使用しているコード抽出&設定サンプルを追加できますか? SessionFactory Beanが設定されていますか? –

+0

DAOはSpringクラスから呼び出されますか?また、スタックトレースにTransactionInterceptorが表示されますか? – sourcedelica

+0

他にも数十もの質問やGoogleの結果がこれを助けてくれましたか? – Bozho

答えて

40

私は、ベース/ジェネリックHibernateのDAO実装クラス(私はメインプログラムで使用DAOによって継承するsaveOrUpdate()メソッドを実装する親クラス)に@Transactionalを追加することで、これを解決するに指定する@Transactionalニーズ、すなわちこのメソッドを実装する実際のクラス私の前提は、子クラスで@Transactionalを宣言した場合、子クラスによって継承されたすべてのメソッドが含まれているということでした。しかし、@Transactional注釈は、クラス内に実装されたメソッドにのみ適用され、クラスによって継承されたメソッドには適用されないようです。私は、プロパティファイルに

session = getHibernateTemplate().getSessionFactory().getCurrentSession(); 

session.beginTransaction(); 

session.createQuery(Qry).executeUpdate(); 

session.getTransaction().commit(); 

を次のように私の休止状態の性質が

私のコードや設定ファイルをファイル変更することで、これを固定

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) 

+3

ちょうどこれを見つけた:http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html "アノテーションが継承されないという事実は、クラスベースのプロキシを使用している場合、トランザクション設定クラスベースのプロキシーインフラストラクチャでは認識されず、オブジェクトはトランザクションプロキシでラップされません(これは明らかに悪いことです)ので、Springチームのアドバイスを受けて、具体的なクラス(および具体的なクラスのメソッド)を@Transactionalアノテーションとともに使用します。 – dev

1

org.springframework.orm.hibernate3.support.OpenSessionInViewFilterがwebappのweb.xml(アプリケーションがwebappの場合)に設定されているか、それに応じて呼び出しをラッピングしていますか?

+0

ありがとうございますが、いいえ、私はこのコードをWebアプリケーションで使用していません。 –

+1

これを確認してください:http://forum.springsource.org/archive/index.php/t-34856.html – mindas

0

あなたの春の文脈から<context:annotation-config />が見つからないため、注釈がスキャンされていません!

+0

提案してくれてありがとう、残念なことに私はこれをアプリケーションコンテキストの設定に追加しようとしましたが、それは喜びをもたらしませんでしたアノテーションを有効にする前にこれを使用する必要はありませんでした)。 –

+0

@TransactionalをDAOメソッドを呼び出すメソッドに追加しようとしましたか? 少し狂っているように見えるかもしれませんが、コントローラ - >サービス - > DAO階層で動作するように注釈が設計されているため、サービスレイヤをスキップしているように見えます。呼び出しメソッドがSpring Bean内にない場合は、サービスレイヤを導入するか、注釈の代わりに宣言的トランザクション管理を使用することができます。 – rjsang

+0

もう一度、ありがとうございます。 @Transactionalを他のクラスに追加することには問題がありますが、問題を解決したベースのDAOクラス(saveOrUpdate()メソッドが定義されています)に追加していました。私は誤って@Transactionalをクラスに追加し、そのクラスによって継承されたすべてのメソッドに影響を与えることを想定していましたが、明らかにそのようには動作しません。そのため、@Transactionalを子DAOクラスに追加すると、そのクラスで実際に定義されているメソッドにのみ影響し、ベース/汎用DAOクラスから継承されたメソッドには影響しません。 –

11

私は、次のエラーを得ました

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 

<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> 

cofigurationファイルのおかげで、
アショク

+0

クール!どうもありがとう!私はSpringのトランザクションアノテーションにバインドしたくありませんでした。 – weekens

7

私は、プロパティを追加した後:

<prop key="hibernate.current_session_context_class">thread</prop> 私のような例外を取得:

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

私はそのプロパティを設定することは良い解決策ではないと思います。 <!-- <prop key="hibernate.current_session_context_class">thread</prop> -->

1.サーブレットのcontext.xmlしたり、ディスパッチャ-servlet.xmlを
3.add @Transactional後<tx:annotation-driven />を2.add:

は最終的に私が問題 "いいえHibernateのSessionはスレッドにバインドしない" 解決します@Serviceと@Repository

1

あなたは子クラスで@Transactionalを持つことができますが、メソッドのそれぞれをオーバーライドして、それが仕事を得るためには、スーパーメソッドを呼び出す必要があります。

例:

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

これは、それがために必要なのは方法のそれぞれのためにそれを設定することができます。

0

私は解決策のためにここに検索today.While同じ問題を持っていた、私の代わりに無意識のうちに

import org.springframework.transaction.annotation.Transactional; 

をインポートする私はそれを変更するのafer

import javax.transaction.Transactional;

をインポートしている愚かな間違いをしたしていますすべてうまくいった。

だから誰かが同じミスをした場合、共有を考えた。

関連する問題