Статьи

Как я решил SpringMVC + Hibernate Ошибка: нет Hibernate Сеанс, связанный с потоком

При разработке веб-приложения с использованием 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;@Service@Transactionalpublic class UserAccountsService{    @Autowired    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