복붙노트

[SPRING] 하이버 네이트 세션이 쓰레드에 바인드되지 않았고, 컨피규레이션은 비 - 트랜젝션 세션의 생성을 허용하지 않는다.

SPRING

하이버 네이트 세션이 쓰레드에 바인드되지 않았고, 컨피규레이션은 비 - 트랜젝션 세션의 생성을 허용하지 않는다.

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)

다음 응용 프로그램 컨텍스트 구성 파일이 있습니다.

<?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 주석을 사용합니다.

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

해결법

  1. ==============================

    1.@Transactional을 기본 / generic Hibernate DAO 구현 클래스 (main 프로그램에서 사용하는 DAO에 상속 된 saveOrUpdate () 메소드를 구현하는 부모 클래스)에 추가하여이를 해결했습니다. 즉, @Transactional을 실제 메소드를 구현하는 클래스 대신 내 가정은 @Transactional을 자식 클래스에 선언하면 자식 클래스에서 상속 된 모든 메서드가 포함 된 것입니다. 그러나 @Transactional 어노테이션은 클래스 내에서 구현 된 메소드에만 적용되고 클래스에 의해 상속 된 메소드에는 적용되지 않는 것으로 보입니다.

    @Transactional을 기본 / generic Hibernate DAO 구현 클래스 (main 프로그램에서 사용하는 DAO에 상속 된 saveOrUpdate () 메소드를 구현하는 부모 클래스)에 추가하여이를 해결했습니다. 즉, @Transactional을 실제 메소드를 구현하는 클래스 대신 내 가정은 @Transactional을 자식 클래스에 선언하면 자식 클래스에서 상속 된 모든 메서드가 포함 된 것입니다. 그러나 @Transactional 어노테이션은 클래스 내에서 구현 된 메소드에만 적용되고 클래스에 의해 상속 된 메소드에는 적용되지 않는 것으로 보입니다.

  2. ==============================

    2.다음과 같은 오류가 발생했습니다.

    다음과 같은 오류가 발생했습니다.

    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)
    

    내 최대 절전 모드 속성 파일을 변경하여이 문제를 해결했습니다.

    hibernate.current_session_context_class=thread
    

    내 코드 및 구성 파일은 다음과 같습니다.

    session =  getHibernateTemplate().getSessionFactory().getCurrentSession();
    
    session.beginTransaction();
    
    session.createQuery(Qry).executeUpdate();
    
    session.getTransaction().commit();
    

    속성 파일

    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>
    

    감사, 아쇽

  3. ==============================

    3.속성을 추가 한 후 :

    속성을 추가 한 후 :

    스레드 나는 예외를 얻는다 :

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

    그래서 나는 그 속성을 설정하는 것이 좋은 해결책이 아니라고 생각합니다.

    마지막으로 "스레드에 바인딩 된 최대 절전 모드 세션 없음"문제를 해결합니다.

    1. thread -> 2. 을 servlet-context.xml 또는 dispatcher-servlet.xml에 추가합니다. 3. @Service와 @Repository 다음에 @Transactional을 추가하십시오.

  4. ==============================

    4.나는 오늘도 똑같은 문제를 안고 있었다. 해결책을 찾기 위해 여기에서 검색하는 동안, 나는 수입 대신에 어리석은 실수를했다.

    나는 오늘도 똑같은 문제를 안고 있었다. 해결책을 찾기 위해 여기에서 검색하는 동안, 나는 수입 대신에 어리석은 실수를했다.

    import org.springframework.transaction.annotation.Transactional;
    

    무의식적으로 나는 수입했다.

    import javax.transaction.Transactional;

    그것을 바꾼 후에 모든 것이 잘 작동했습니다.

    그래서 누군가 공유하는 실수를한다면, 공유 할 생각입니다.

  5. ==============================

    5.webapp의 web.xml에서 org.springframework.orm.hibernate3.support.OpenSessionInViewFilter를 설정 했습니까 (애플리케이션이 웹 애플리케이션이라고 가정), 또는 그에 따라 호출을 래핑합니까?

    webapp의 web.xml에서 org.springframework.orm.hibernate3.support.OpenSessionInViewFilter를 설정 했습니까 (애플리케이션이 웹 애플리케이션이라고 가정), 또는 그에 따라 호출을 래핑합니까?

  6. ==============================

    6.하위 클래스에 @Transactional을 가질 수 있지만 작동 시키려면 각 메서드를 재정의하고 super 메서드를 호출해야합니다.

    하위 클래스에 @Transactional을 가질 수 있지만 작동 시키려면 각 메서드를 재정의하고 super 메서드를 호출해야합니다.

    예:

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

    이렇게하면 필요한 각 메소드에 대해이를 설정할 수 있습니다.

  7. ==============================

    7.오류가 발생할 때마다 즉시 따라야합니다.

    오류가 발생할 때마다 즉시 따라야합니다.

    클래스를 구현하는 각 메소드마다 @Transactional 어노테이션을 추가하십시오.

  8. ==============================

    8.어노테이션이 스캔되지 않도록 스프링 컨텍스트에서 가 누락되었습니다!

    어노테이션이 스캔되지 않도록 스프링 컨텍스트에서 가 누락되었습니다!

  9. from https://stackoverflow.com/questions/4961636/no-hibernate-session-bound-to-thread-and-configuration-does-not-allow-creation by cc-by-sa and MIT license