При разработке веб-приложения с использованием SpringMVC и Hibernate я получил сообщение «Сессия Hibernate не связана с исключением потока» из-за некоторой проблемы конфигурации.
Здесь я собираюсь объяснить, как я решил проблему.
Я использовал подход аннотации SpringMVC @Controller и сконфигурировал веб-конфигурацию Spring в dispatcher-servlet.xml следующим образом:
<beans> <context:annotation-config"/> <context:component-scan base-package="com.sivalabs"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"></bean> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="Messages"></bean></beans>
Я настроил свои бизнес-сервисы и DAO в applicationContext.xml следующим образом:
<beans> <context:component-scan base-package="com.sivalabs"/> <context:property-placeholder location="classpath:app-config.properties"/> <tx:annotation-driven/> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory"></bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="mappingResources"> <list> <value>UserAccount.hbm.xml</value> <value>Contact.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> </props> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> ..... ..... </bean></beans>
Чтобы включить управление транзакциями, я использовал аннотацию @Transactional в своих бизнес-сервисах.
package com.sivalabs.homeautomation.useraccounts; class UserAccountsService{ private UserAccountsDAO userAccountsDAO; public UserAccount login(Credentials credentials) { return userAccountsDAO.login(credentials); }}
Но когда я вызвал метод UserAccountsService.login (), я получил следующую ошибку:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:544) at com.sivalabs.homeautomation.useraccounts.UserAccountsDAO.login(UserAccountsDAO.java:30) at com.sivalabs.homeautomation.useraccounts.UserAccountsService.login(UserAccountsService.java:25) at com.sivalabs.homeautomation.useraccounts.LoginController.login(LoginController.java:51)
Здесь я включил настройку на основе аннотаций, используя <context: annotation-config /> .
Я настроил базовый пакет, содержащий компоненты Spring, используя <context: component-scan base-package = «com.sivalabs» /> .
Я включил управление транзакциями на основе аннотаций, используя <tx: annotation-driven /> и @Transactional.
Но все же я получаю исключение «Нет Hibernate Session связанный с потоком». Почему?
Вот причина:
В справочной документации Spring мы можем найти упомянутое ниже важное примечание:
<tx: annotation-driven /> ищет только @Transactional для bean-компонентов в том же контексте приложения, в котором он определен. Это означает, что если вы поместите <tx: annotation-driven /> в WebApplicationContext для DispatcherServlet, он только проверяет для бинов @Transactional в ваших контроллерах, а не в ваших сервисах.
Поэтому, когда мое приложение запускается сначала, оно загружает компоненты, настроенные в dispatcher-servlet.xml, а затем просматривает applicationContext.xml.
Поскольку я упомянул «com.sivalabs» в качестве моего базового пакета для сканирования бинов Spring, мои бизнес-сервисы и DAO, аннотированные @Service, @Repository также будут загружаться контейнером. Позже, когда Spring пытается загрузить bean-компоненты из applicationContext.xml, он не загружает мои службы и DAO, поскольку они уже загружены родительским ApplicaationContext. Таким образом, <tx: annotation-driven /> не будет применяться для бизнес-сервисов или DAO с аннотацией @Transactional.
Решение
1. Если вы придерживаетесь послойного подхода: возможно, вы можете поместить все свои контроллеры в один пакет, скажем, com.sivalabs.appname.web.controllers.
Затем измените конфигурацию <context: annotation-config /> в dispatcher-servlet. XML как:
<context:component-scan base-package="com.sivalabs.appname.web.controllers"/>
При этом только контроллеры, аннотированные @Controller в пакете com.sivalabs.appname.web.controllers, будут загружаться родительским ApplicationContext, а остальные службы DAO будут загружаться дочерним ApplicationContext.
Решение 2. Если вы используете подход «пакет за функцией»:
Если вы используете подход «пакет за функцией», вы поместите все Controller, Service, DAO, связанные с одной функцией, в один пакет.
При этом контроллеры, сервисы, DAO будут охватывать все пакеты.
Затем измените конфигурацию <context: annotation-config /> в dispatcher-servlet.xml следующим образом:
<context:component-scan base-package="com.sivalabs" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan>
При этом только контроллеры, аннотированные @Controller, будут загружены родительским ApplicationContext.
А Сервисы, DAO будут загружаться дочерним ApplicationContext, и будет применяться <tx: annotation-driven />.
От: http://sivalabs.blogspot.com/2011/05/springmvc-hibernate-error-no-hibernate.html