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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7040052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 18:25:21  来源:igfitidea点击:

Problem with transactions: No Hibernate Session bound to thread

javahibernatespringtransactions

提问by Nofate

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.

我重构了我的服务层以作为通用组件工作。之后,对我的控制器的所有请求开始抛出 org.hibernate.HibernateException: No Hibernate Session bound to thread,并且配置不允许在此处创建非事务性会话。

I searched over the internet and found common reasons:

我在互联网上搜索,发现了常见的原因:

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

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
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 implementationpublic abstract class HibernateGenericDao implements AbstractDao {

通用 DAO 实现公共抽象类 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>

回答by Nofate

It seems I've found my mistake. Both root-context.xmland servlet-context.xmlcontain 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.xml

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

回答by JB Nizet

Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactionalannotation, as opposed to annotating interfaces.

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

Have you tried putting the @Transactionalannotation on the InfoJournalServiceImplclass? Also, have you checked that you have a <tx:annotation-driven transaction-manager="..." />in your spring config, as explained in the Spring documentation?

你有没有试过把@Transactional注释放在InfoJournalServiceImpl班级上?另外,您是否检查<tx:annotation-driven transaction-manager="..." />过您的 spring 配置中有一个,如Spring 文档中所述