2014-11-11 5 views
1

Я прочитал множество сообщений людей с похожими проблемами, но я все еще не могу заставить свой код работать.Нет сеанса для текущей темы: Spring 3 и Hibernate 4 (с использованием аннотации @PostConstruct)

«No Session found for current thread» возникает, когда я переместил @Transactional с Дао на сервисный уровень. Действительно, я убежден, что привязка транзакции к единому доступу является пустой тратой ресурсов. Кстати, моя конфигурация веб-приложение является очень распространенным явлением:

  • Spring 3.1.2
  • Hibernate 4

Я не могу понять эту проблему, я проверил, что знаменитый <tx:annotation-driven> является в нужном месте, а также правильно <context:component-scan ...>. Я предполагаю, что весна нуждается в том, чтобы @Transactional также был помещен поверх классов, имеющих заводскую ссылку на сессию, но для меня это кажется немного нелогичным.

вот сервлет

<!-- auto-detects and registers annotated classes belonging to the base package--> 
<context:component-scan base-package="com.x.y.controllers" /> 
<!-- flips on all the annotation-driven capabilities for Spring MVC --> 
<mvc:annotation-driven /> 
... 

вот Context

<!-- enables the @Transactional annotantions --> 
<tx:annotation-driven transaction-manager="transactionManager"/> 

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<!-- auto-detects and registers annotated classes belonging to the base package--> 
<context:component-scan base-package="com.x.y.service" /> 
<context:component-scan base-package="com.x.y.aop" /> 
<context:component-scan base-package="com.x.y.model" /> 


<bean id="dataSource" 
class = "com.mchange.v2.c3p0.ComboPooledDataSource" 
destroy-method="close"> 
    <property name="driverClass" value="${database.driver.className}" /> 
    <property name="jdbcUrl" value="${database.uri}" /> 
    <property name="user" value="${database.username}" /> 
    <property name="password" value="${database.password}" /> 

    <!-- these are C3P0 properties -->  
    <property name="checkoutTimeout" value="30000" /> 
    <property name="initialPoolSize" value="10" /> 
    <property name="maxIdleTime" value="30" /> 
    <property name="minPoolSize" value="10" /> 
    <property name="maxPoolSize" value="100" /> 
    <property name="maxStatements" value="200" /> 
    <property name="testConnectionOnCheckout" value="false" /> 
    <property name="testConnectionOnCheckin" value="true" /> 
    <property name="preferredTestQuery" value="SELECT 1" /> 
    <property name="idleConnectionTestPeriod" value="30" /> 
</bean> 

<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${database.hibernate.dialect}</prop> 
      <prop key="hibernate.hbm2ddl.auto">update</prop> 
      <prop key="hibernate.cache.use_second_level_cache">true</prop> 
      <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> 
      <prop key="hibernate.generate_statistics">true</prop> 
      <prop key="hibernate.show_sql">false</prop> 
      <prop key="hibernate.connection.SetBigStringTryClob">true</prop> 
      <prop key="hibernate.jdbc.batch_size">0</prop>   
     </props> 
    </property> 
</bean> 

вот Service

package com.x.y.service.initialization; 

@Component 
public class Initializer { 

    @Autowired 
    @Qualifier("userDaoImpl") 
    private UserDao userDao; 

    @PostConstruct 
    @Transactional 
    public void init() 
    { 
     ProfiledUser admin = userDao.loadByUsername("Administrator"); 

     ... 
    } 
} 

и вот DAO

package com.x.y.model.dao; 

@Repository(value="userDaoImpl") 
public class UserDaoImpl implements UserDao{ 

    @Autowired 
    @Qualifier("sessionFactory") 
    protected SessionFactory sessionFactory; 

    public ProfiledUser loadByUsername(String username) 
    { 
     Session session = sessionFactory.getCurrentSession(); 
     Criteria criteria = session.createCriteria(ProfiledUser.class); 
     criteria.add(Restrictions.eq("username", username)); 
     ProfiledUser user = (ProfiledUser) criteria.uniqueResult(); 
     if(user != null) 
      return user; 
     else 
      return null; 
    } 
} 

и вот StackTrace

ERROR: org.springframework.web.context.ContextLoader - Context initialization failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initializer': Invocation of init method failed; nested exception is org.hibernate.HibernateException: No Session found for current thread 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:135) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1448) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469) 
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383) 
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283) 
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206) 
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705) 
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057) 
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840) 
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057) 
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463) 
    at org.apache.catalina.core.StandardService.start(StandardService.java:525) 
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754) 
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) 
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414) 
Caused by: org.hibernate.HibernateException: No Session found for current thread 
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:881) 
    at com.x.y.model.dao.UserDaoImpl.loadByUsername(UserDaoImpl.java:37) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at com.sun.proxy.$Proxy15.loadByUsername(Unknown Source) 
    at com.x.y.service.initialization.Initializer.init(Initializer.java:46) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:346) 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:299) 
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:132) 
    ... 29 more 

ответ

2

возможно сво Erroneus configufation как следует из других ответов, однако, иметь в виду, что вы не должны аннотировать ваш @PostConstruct с @Transactional и ожидайте его работы. В тот момент, когда выполняется @PostConstruct, не гарантируется, что ваш код будет обрабатываться транзакционной семантикой. Причина в том, что @PostConstruct гарантирует только то, что все зависимости были введены, и что компоновка компонента завершена, но это не означает, что полный контекст завершил загрузку (нет гарантий того, что транзакционная аппаратура выполнена).

Если вам действительно нужны транзакции в вашем @PostConstruct, перейдите программным способом.Это только мои два цента, но вполне может быть причиной для вашего вопроса

UPDATE

Просто нашел blog об этом, где они советуют использование @PostInitialize как это гарантирует назвать после завершения контекст загружается

+0

это может быть проблемой. Пожалуйста, учтите, что мой класс «Initializer» должен запускаться, когда приложение готово к работе. Вероятно, '@ PostConstruct' является излишним. Предлагаете ли вы другие аннотации, чтобы сказать: «Хорошо, веб-приложение полностью загружено, теперь этот метод выполняется». – MaVVamaldo

+0

yeps, только что отредактированный ответ @PostiInitialize должен работать, если нет, вы можете ввести TransactionManager и использовать TransactionTemplate для обработки транзакции программно (оставив @PostConstruct) –

+0

, вы выиграли гонку. Это определенно проблема PostConstruct. С @PostInitialize все идет гладко, как масло. Я собираюсь изменить название моего вопроса, чтобы люди могли правильно решить проблему. – MaVVamaldo

0

Вы объявляете «источник данных» и «сессионный завод», но вам не хватает его «транзакционный менеджер»

попробуйте добавить это к контексту пружинной:

<bean id="transactionManager" 
     class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

Я надеюсь, что это помогает

+0

диспетчер транзакций включен в контекст, более или менее в строке 3, прямо под ''. – MaVVamaldo

+0

Извините, я не видел: -O – fdm

0

Вы можете определить менеджер транзакций в спящем-context.xml

<tx:annotation-driven transaction-manager="hbnTransactionManager" /> 
    <bean id="hbnTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory" /> 
     </property> 
    </bean> 
+0

учтите, что диспетчер транзакций уже находится в файле контекста. Более или менее ay строка 3. – MaVVamaldo

0

Поскольку вы непосредственно используете SessionFactory в своем DAO, вы должны иметь следующую конфигурацию hibernate.current_session_context_class, а ваша конфигурация SessionFactory должна выглядеть следующим образом.

<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">${database.hibernate.dialect}</prop> 
      <prop key="hibernate.hbm2ddl.auto">update</prop> 
      <prop key="hibernate.cache.use_second_level_cache">true</prop> 
      <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> 
      <prop key="hibernate.generate_statistics">true</prop> 
      <prop key="hibernate.show_sql">false</prop> 
      <prop key="hibernate.connection.SetBigStringTryClob">true</prop> 
      <prop key="hibernate.jdbc.batch_size">0</prop> 
      <!-- Add this configuration --> 
      <prop key="hibernate.current_session_context_class">thread</prop>   
     </props> 
    </property> 
</bean> 
0

У меня была та же проблема.

Я использовал настройку на основе аннотации, я настроил sessionfactory, datasource и диспетчер транзакций на все. но я не подавал аннотацию @EnableTransactionManagement в классе AppConfig.

Код выглядит следующим образом после добавления аннотации транзакции.

@Configuration 
@ComponentScan("com.bmp.*") 
@EnableWebMvc 
@PropertySource("classpath:${env}.properties") 
@EnableTransactionManagement 
public class AppConfig { 
----- 
} 

Вышеупомянутые аннотации разрешили мою проблему.

Голосовать, если это решает, ваша проблема.

Смежные вопросы