简体   繁体   English

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

[英]Problem with transactions: No Hibernate Session bound to thread

I refactored my service layer to work as generic component.我重构了我的服务层以作为通用组件工作。 After that all request to my controller began to throw org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here. After that all request to my controller began to throw org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.

I searched over the internet and found common reasons:我在网上搜索了一下,发现了常见的原因:

  1. Lack of @Transaction annotation.缺少@Transaction 注释。
  2. Usage of hibernate.current_session_context_class and hibernate.transaction_factory_class options. hibernate.current_session_context_class 和 hibernate.transaction_factory_class 选项的使用。
  3. Direct calls to sessionFactory.openSession().直接调用 sessionFactory.openSession()。
  4. Using BeanFactory instead of ApplicationContext.使用 BeanFactory 而不是 ApplicationContext。
  5. Several instances of DAO class. DAO class 的几个实例。

But it seems that none of them are related to my case.但似乎它们都与我的情况无关。

I would appreciate any help as I've spent all my day with this exception.我将不胜感激任何帮助,因为我整天都在处理这个例外。

Stacktrace堆栈跟踪

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

@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;
    }
} 

Generic service interface通用服务接口

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);
} 

Generic service implementation通用服务实现

@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();
}

Concrete service interface具体服务接口

public interface InfoJournalService extends AbstractCRUDService<InfoJournalEntry, Long>     }

Concrete service implementation具体服务实现

@Service("infoJournalService")
public class InfoJournalServiceImpl extends AbstractCRUDServiceBean<InfoJournalEntry, Long> implements InfoJournalService {

    @Autowired
    private InfoJournalDao infoJournalDao;

    @Override
    public AbstractDao<InfoJournalEntry, Long> getDao() {
        return infoJournalDao;
    }
}

Generic DAO interface通用 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();
}

Generic DAO implementation public abstract class HibernateGenericDao implements AbstractDao {通用 DAO 实现public abstract class HibernateGenericDao 实现 AbstractDao {

    @Autowired
    protected SessionFactory sessionFactory;

    //....

    @SuppressWarnings("unchecked")
    public List<E> findAll() {
        return sessionFactory.getCurrentSession().createCriteria(getEntityClass()).list();
    }

    public abstract Class getEntityClass();
}

Concrete DAO implementation具体的DAO实现

@Repository("infoJournalDao")
public class InfoJournalDaoImpl extends HibernateGenericDao<InfoJournalEntry, Long>     implements InfoJournalDao {

    @Override
    public Class getEntityClass() {
        return InfoJournalEntry.class;
    }
}

root-context.xml根上下文.xml

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

datasource.xml数据源.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 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>

It seems I've found my mistake.看来我发现了我的错误。 Both root-context.xml and servlet-context.xml contain the same line <context:component-scan base-package="ru.centr_in.rescuer.server" /> . root-context.xmlservlet-context.xml都包含相同的行<context:component-scan base-package="ru.centr_in.rescuer.server" />

Now I specified base packages in the following way:现在我通过以下方式指定基本包:

root-context.xml根上下文.xml

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

and servlet-context.xmlservlet-context.xml

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

And now everything works.现在一切正常。

Thanks to Miles from Entities Not Persisting - Spring + Hibernate + JPA感谢实体的里程不存在 - Spring + Hibernate + JPA

Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. Spring 建议您仅使用@Transactional注释来注释具体类(和具体类的方法),而不是注释接口。

Have you tried putting the @Transactional annotation on the InfoJournalServiceImpl class?您是否尝试将@Transactional注释放在InfoJournalServiceImpl class 上? Also, have you checked that you have a <tx:annotation-driven transaction-manager="..." /> in your spring config, as explained in the Spring documentation ?此外,您是否检查过您的 spring 配置中是否有<tx:annotation-driven transaction-manager="..." /> ,如Spring 文档中所述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM