Проблема с транзакциями: сессия Hibernate не связана с потоком - PullRequest
2 голосов
/ 12 августа 2011

Я реорганизовал свой сервисный слой, чтобы он работал как общий компонент. После этого все запросы к моему контроллеру начали выдавать 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.

Но, похоже, ни один из них не имеет отношения к моему делу.

Буду признателен за любую помощь, поскольку я провел весь день с этим исключением.

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

сервлет-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 ]

7 голосов
/ 13 августа 2011

Кажется, я нашел свою ошибку.И root-context.xml, и servlet-context.xml содержат одну и ту же строку <context:component-scan base-package="ru.centr_in.rescuer.server" />.

Теперь я указал базовые пакеты следующим образом:

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

и servlet-context.xml

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

И теперь все работает.

Благодаря Милям из Сущности не сохранились- Весна + Спящий + JPA

0 голосов
/ 12 августа 2011

Spring рекомендует, чтобы вы аннотировали только конкретные классы (и методы конкретных классов) с аннотацией @Transactional, в отличие от аннотирования интерфейсов.

Вы пытались поместить аннотацию @Transactional в InfoJournalServiceImpl учебный класс?Кроме того, проверили ли вы, что в конфигурации Spring у вас есть <tx:annotation-driven transaction-manager="..." />, как описано в документации Spring ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...