开发者

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.

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.

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.HttpC开发者_运维问答onnection.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

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 {

    @Autowired
    protected SessionFactory sessionFactory;

    //....

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

    public abstract Class getEntityClass();
}

Concrete DAO implementation

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

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

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


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" />.

Now I specified base packages in the following way:

root-context.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

<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 recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces.

Have you tried putting the @Transactional annotation on the 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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜