事务问题:没有Hibernate Session绑定到线程

时间:2011-08-12 12:28:05

标签: java hibernate spring transactions

我重构了我的服务层以作为通用组件工作。之后,我的控制器的所有请求都开始抛出org.hibernate.HibernateException:没有Hibernate Session绑定到线程,并且配置不允许在这里创建非事务性的。

我在互联网上搜索并找到了常见的原因:

  1. 缺少@Transaction注释。
  2. 使用hibernate.current_session_context_class和hibernate.transaction_factory_class选项。
  3. 直接调用sessionFactory.openSession()。
  4. 使用BeanFactory而不是ApplicationContext。
  5. DAO类的几个实例。
  6. 但似乎没有一个与我的案件有关。

    我很感激任何帮助,因为我花了这么多时间来处理这个例外。

    堆栈跟踪

    [INFO] 2011-08-12 15:42:49,383 [btpool0-0] INFO  ru.centr_in.rescuer.server.web.InfoJournalController - FETCH started: all
    [INFO] 2011-08-12 15:42:49,383 [btpool0-0] DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Opening Hibernate Session
    [INFO] 2011-08-12 15:42:49,383 [btpool0-0] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13131493693
    [INFO] 2011-08-12 15:42:49,383 [btpool0-0] DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Closing Hibernate Session
    [INFO] 2011-08-12 15:42:49,383 [btpool0-0] DEBUG org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [ru.centr_in.rescuer.server.web.InfoJournalController@14e1b74]: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    [INFO] 2011-08-12 15:42:49,384 [btpool0-0] DEBUG org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [ru.centr_in.rescuer.server.web.InfoJournalController@14e1b74]: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    [INFO] 2011-08-12 15:42:49,384 [btpool0-0] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [ru.centr_in.rescuer.server.web.InfoJournalController@14e1b74]: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    [INFO] 2011-08-12 15:42:49,384 [btpool0-0] DEBUG org.springframework.web.servlet.DispatcherServlet - Could not complete request
    [INFO] org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    [INFO]  at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
    [INFO]  at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
    [INFO]  at ru.centr_in.rescuer.server.dao.HibernateGenericDao.findAll(HibernateGenericDao.java:41)
    [INFO]  at ru.centr_in.rescuer.server.service.AbstractCRUDServiceBean.findAll(AbstractCRUDServiceBean.java:21)
    [INFO]  at ru.centr_in.rescuer.server.web.InfoJournalController.getInfoJournalEntries(InfoJournalController.java:40)
    [INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [INFO]  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    [INFO]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    [INFO]  at java.lang.reflect.Method.invoke(Method.java:597)
    [INFO]  at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    [INFO]  at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    [INFO]  at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    [INFO]  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    [INFO]  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    [INFO]  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    [INFO]  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    [INFO]  at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    [INFO]  at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    [INFO]  at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    [INFO]  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    [INFO]  at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    [INFO]  at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    [INFO]  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    [INFO]  at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    [INFO]  at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    [INFO]  at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
    [INFO]  at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    [INFO]  at org.mortbay.jetty.Server.handle(Server.java:324)
    [INFO]  at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    [INFO]  at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
    [INFO]  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
    [INFO]  at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    [INFO]  at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    [INFO]  at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    [INFO]  at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
    

    控制器

    @Controller
    public class InfoJournalController {
    
        @Autowired
        private InfoJournalService infoJournalService;
    
        @RequestMapping(value="/infoJournal", method=RequestMethod.GET)
        public @ResponseBody InfoJournalEntry[] getInfoJournalEntries() {
    
            List<InfoJournalEntry> entries = infoJournalService.findAll();
            InfoJournalEntry[] result = new InfoJournalEntry[entries.size()];
            entries.toArray(result);
            return result;
        }
    } 
    

    通用服务界面

    public interface AbstractCRUDService<E, PK extends Serializable> {
        void save(E entity);
        List<E> findAll();
        E findById(PK id);
        void delete(E entity);
        void update(E entity);
    } 
    

    通用服务实施

    @Transactional
    public abstract class AbstractCRUDServiceBean<E, PK extends Serializable> implements   AbstractCRUDService<E, PK> {
    
        //....
    
        @Transactional
        public List<E> findAll() {
            return getDao().findAll();
        }
    
        //....
    
        public abstract AbstractDao<E, PK> getDao();
    }
    

    具体服务界面

    public interface InfoJournalService extends AbstractCRUDService<InfoJournalEntry, Long>     }
    

    具体服务实施

    @Service("infoJournalService")
    public class InfoJournalServiceImpl extends AbstractCRUDServiceBean<InfoJournalEntry, Long> implements InfoJournalService {
    
        @Autowired
        private InfoJournalDao infoJournalDao;
    
        @Override
        public AbstractDao<InfoJournalEntry, Long> getDao() {
            return infoJournalDao;
        }
    }
    

    通用DAO界面

    public abstract class HibernateGenericDao<E, PK extends Serializable> implements AbstractDao<E, PK> {
    
        @Autowired
        protected SessionFactory sessionFactory;
    
        //....
    
        @SuppressWarnings("unchecked")
        public List<E> findAll() {
            return sessionFactory.getCurrentSession().createCriteria(getEntityClass()).list();
        }
    
        public abstract Class getEntityClass();
    }
    

    通用DAO实施     公共抽象类HibernateGenericDao实现了AbstractDao {

        @Autowired
        protected SessionFactory sessionFactory;
    
        //....
    
        @SuppressWarnings("unchecked")
        public List<E> findAll() {
            return sessionFactory.getCurrentSession().createCriteria(getEntityClass()).list();
        }
    
        public abstract Class getEntityClass();
    }
    

    具体的DAO实施

    @Repository("infoJournalDao")
    public class InfoJournalDaoImpl extends HibernateGenericDao<InfoJournalEntry, Long>     implements InfoJournalDao {
    
        @Override
        public Class getEntityClass() {
            return InfoJournalEntry.class;
        }
    }
    

    根context.xml中

      <context:annotation-config />
      <context:component-scan base-package="ru.centr_in.rescuer.server" />
      <import resource="datasource.xml" />
    

    datasource.xml

     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" >
      <property name="sessionFactory" ref="sessionFactory" />
     </bean>
    
     <tx:annotation-driven transaction-manager="transactionManager"/>  
    
     <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="location">
        <value>WEB-INF/database.properties</value>
      </property>
     </bean>
    
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
     </bean>
    
     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
       <property name="dataSource" ref="dataSource"/>
       <property name="configurationClass">
         <value>org.hibernate.cfg.AnnotationConfiguration</value>
       </property>
       <property name="hibernateProperties">
         <props>
           <prop key="hibernate.show_sql">true</prop>
           <prop key="hibernate.hbm2ddl.auto">create</prop> 
           <prop key="hibernate.dialect">${jdbc.dialect}</prop>
           <prop key="hibernate.connection.charset">UTF-8</prop>
         </props>
       </property>
    
       <property name="annotatedClasses">
            <list>
                <value>ru.centr_in.rescuer.server.domain.InfoJournalEntry</value>
            </list>
       </property>
     </bean>
    

    servlet的context.xml中

     <annotation-driven/>
     <context:component-scan base-package="ru.centr_in.rescuer.server" />
    
     <resources mapping="/resources/**" location="/resources/"/>
     <resources mapping="/Rescuer.html" location="/Rescuer.html"/>
     <resources mapping="/Rescuer/**" location="/Rescuer/"/>
    
     <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/"/>
        <beans:property name="suffix" value=".jsp"/>
     </beans:bean>
    

2 个答案:

答案 0 :(得分:7)

我似乎发现了自己的错误。 root-context.xmlservlet-context.xml都包含相同的行<context:component-scan base-package="ru.centr_in.rescuer.server" />

现在我按以下方式指定了基础包:

<强>根context.xml中

<context:component-scan base-package="ru.centr_in.rescuer.server.service" />
<context:component-scan base-package="ru.centr_in.rescuer.server.dao" />

servlet-context.xml

<context:component-scan base-package="ru.centr_in.rescuer.server.web" />

现在一切正常。

感谢来自Entities Not Persisting - Spring + Hibernate + JPA

的Miles

答案 1 :(得分:0)

Spring建议您只使用@Transactional注释来注释具体类(以及具体类的方法),而不是注释接口。

您是否尝试将@Transactional注释放在InfoJournalServiceImpl课程上?另外,您是否检查过弹簧配置中有<tx:annotation-driven transaction-manager="..." />,如the Spring documentation中所述?