2014-10-25 1 views
10

sto ottenendo la seguente eccezione quando si tenta di utilizzare i miei @Service classi annotate:HibernateException: Impossibile ottenere sessione di transazione sincronizzata per thread corrente

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final] 
    at webapp.base.repository.GenericDaoImpl.saveOrUpdate(GenericDaoImpl.java:59) ~[base-0.0.1-SNAPSHOT-classes.jar:na] 
    at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:19) ~[site-0.0.1-SNAPSHOT.jar:na] 
    at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:14) ~[site-0.0.1-SNAPSHOT.jar:na] 
    at com.example.service.PageViewServiceImpl.savePageView(PageViewServiceImpl.java:26) ~[site-0.0.1-SNAPSHOT.jar:na] 
    at com.example.interceptor.PageViewInterceptor.preHandle(PageViewInterceptor.java:29) ~[site-0.0.1-SNAPSHOT.jar:na] 
    at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api-3.0.jar:na] 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api-3.0.jar:na] 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:466) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:337) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:427) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:200) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [tomcat-catalina-7.0.52.jar:7.0.52] 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote-7.0.52.jar:7.0.52] 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote-7.0.52.jar:7.0.52] 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) [tomcat-coyote-7.0.52.jar:7.0.52] 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_65] 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_65] 
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_65] 

Il mio modo di inizializzare la mia domanda è complicata così ho bisogno per fornire un collegamento al codice base completo per ottenere ulteriori informazioni: https://github.com/dtrunk90/webapp-base. Lo sto usando come overlay di tipo Maven.

E qui è il codice necessario:

Initializer (da webapp-base):

public abstract class AbstractWebApplicationInitializer extends AbstractDispatcherServletInitializer { 
    @Override 
    protected String[] getServletMappings() { 
     return new String[] {"/*"}; 
    } 

    @Override 
    protected Filter[] getServletFilters() { 
     CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); 
     encodingFilter.setEncoding("UTF-8"); 
     encodingFilter.setForceEncoding(true); 
     return new Filter[] {encodingFilter}; 
    } 

    @Override 
    protected WebApplicationContext createRootApplicationContext() { 
     AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 

     ConfigurableEnvironment environment = rootContext.getEnvironment(); 
     environment.setDefaultProfiles("production"); 

     PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles()); 
     String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages"); 
     rootContext.scan(basePackages); 

     return rootContext; 
    } 

    @Override 
    protected WebApplicationContext createServletApplicationContext() { 
     return new AnnotationConfigWebApplicationContext(); 
    } 
} 

Initializer (dal mio webapp):

public class WebApplicationInitializer extends AbstractWebApplicationInitializer { 
} 

@Configuration (da webapp-base):

@Configuration 
@EnableTransactionManagement 
public class TransactionConfiguration { 
    @Bean 
    public DataSource dataSource() throws IOException { 
     Properties conProps = PropertyUtil.getInstance().getProperties("jdbc"); 
     if (conProps.containsKey("url")) { 
      DriverManagerDataSource dataSource = new DriverManagerDataSource(conProps.getProperty("url"), conProps); 
      dataSource.setDriverClassName(conProps.getProperty("driverClassName")); 
      return dataSource; 
     } 

     return null; 
    } 

    @Bean 
    public SessionFactory sessionFactory() throws IOException { 
     DataSource dataSource = dataSource(); 
     if (dataSource != null) { 
      LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource); 
      sessionBuilder.scanPackages(PropertyUtil.getInstance().getPropertySplitTrimmed("hibernate", "packagesToScan")); 
      sessionBuilder.addProperties(PropertyUtil.getInstance().getProperties("hibernate")); 
      return sessionBuilder.buildSessionFactory(); 
     } 

     return null; 
    } 

    @Bean 
    public HibernateTransactionManager transactionManager() throws IOException { 
     SessionFactory sessionFactory = sessionFactory(); 
     if (sessionFactory == null) { 
      return null; 
     } 

     return new HibernateTransactionManager(sessionFactory); 
    } 
} 

@Configuration (dal mio webapp):

@Configuration 
public class MainConfiguration extends WebMvcConfigurerAdapter { 
    @Autowired 
    private PageViewInterceptor pageViewInterceptor; // Is annotated with @Component 

    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     registry.addInterceptor(pageViewInterceptor); 
    } 
} 

@Service:

@Service 
public class PageViewServiceImpl implements PageViewService { 
    @Autowired 
    private PageViewDao pageViewDao; 

    @Override 
    public void savePageView(long ip, String visitPage, String userAgent) { 
     PageView obj = new PageView(); 
     obj.setVisitDate(new Date()); 
     obj.setUserAgent(userAgent); 
     obj.setPage(visitPage); 
     obj.setIp(ip); 

     pageViewDao.saveOrUpdate(obj); 
    } 
} 

@Repository:

@Repository 
public class PageViewDaoImpl extends GenericDaoImpl<PageView, Long> implements PageViewDao { 
    @Override 
    public void saveOrUpdate(PageView obj) { 
     if (!obj.isBot()) { 
      super.saveOrUpdate(obj); 
     } 
    } 
} 

public abstract class GenericDaoImpl<T extends Identifier<I>, I extends Serializable> implements GenericDao<T, I> { 
    @Autowired 
    private SessionFactory sessionFactory; 

    public SessionFactory getSessionFactory() { 
     if (sessionFactory == null) { 
      throw new IllegalStateException("SessionFactory has not been set on DAO before usage"); 
     } 

     return sessionFactory; 
    } 

    @Transactional 
    public void saveOrUpdate(T obj) { 
     getSessionFactory().getCurrentSession().saveOrUpdate(obj); 
    } 
} 

allora io sono autowiring PageViewService e utilizzare i suoi metodi.

So che ci sono diverse domande con lo stesso problema qui, ma ho già controllato tutto:

Could not obtain transaction-synchronized Session for current thread

  • @EnableTransactionManagement è fornito
  • Servizi wil essere autowired come interfacce

HibernateException: Could not obtain transaction-synchronized Session for current thread

  • Controllato per @Transactional ovunque io uso getSessionFactory().getCurrentSession()

Spring Hibernate - Could not obtain transaction-synchronized Session for current thread

  • @EnableTransactionManagement è fornito
  • controllati per @Transactional ovunque io uso getSessionFactory().getCurrentSession()

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread

  • Non c'è una risposta utile.Voglio la scansione dei componenti per tutti i miei componenti, non solo controller
+0

Non vedo alcuna annotazione Transazionale sul metodo 'saveOrUpdate()'. –

+0

Causa 'super.saveOrUpdate()' ce l'ha. Ma aggiungere l'annotazione anche lì sta ancora dando la stessa eccezione. – dtrunk

+2

Quello che sospetto è che tu abbia un contesto radice primaverile, dove viene applicata la configurazione transazionale, e un contesto web spring, dove non lo è. E i servizi e i DAO dovrebbero essere dichiarati/scansionati solo nel contesto radice, ma sono anche disponibili nel contesto web.In tal caso, i web bean ottengono un'istanza di DAO diversa da quella nel contesto di root e che non è delegata dall'interceptor della transazione. –

risposta

7

Guardando il tuo registro, posso immediatamente capire che le impostazioni della transazione sono impostate erroneamente. Questo perché non c'è nessuna chiamata TransactionInterceptor nella traccia dello stack.

Il TransactionInterceptor viene chiamato dai proxy del servizio Spring quando i controller Web chiamano i metodi di servizio effettivi.

  1. Assicurarsi di utilizzare le classi primavera hibernate4:

    org.springframework.orm.hibernate4.HibernateTransactionManager 
    
  2. Non escludere @Transactional metodi, ma utilizzare un modello di modelli, invece.

  3. Provare a utilizzare JPATransactionManager invece così si può iniettare la corrente EntityManager con l'@PersistenceContext annotazioni invece. Questo è molto più elegante di chiamare sessionFactory.getCurrentSession() in ogni metodo DAO.

+0

1. Assicurato: https://github.com/dtrunk90/webapp-base/blob/master/base/src/main/java/webapp/base/config/TransactionConfiguration.java#L12 2. Ho creato un modello modello (non ha risolto il problema) 3. Voglio usare Hibernate, non JPA. – dtrunk

+0

Il passaggio a JpaTransactionManager funziona. Non ha risolto il problema in realtà, ma ti darò il +200. Devo usare 'EntityManager.createQuery (String, Class)' per ottenere un elenco basato su una chiave esterna o su altri campi? E 'davvero brutto come Hibernate usava le classi '@ Entity' per questo. Quindi non ho bisogno di scrivere querys SQL. – dtrunk

+0

È possibile utilizzare la sintassi JPQL o HQL purché si utilizzi Hibernate come provider JPQ. È anche possibile utilizzare le query native se lo si desidera, ma createQuery utilizza JPQL/HQL in modo da non dover utilizzare FK direttamente come nelle query SQL. Con le query sull'entità si usa semplicemente la direttiva * join * sulle associazioni navigabili. –

2

Uno

È necessario utilizzare @Transactional per @Service e @Repository. Consente a Spring di applicare e creare proxy con il supporto delle transazioni.

Nel codice la classe @Service non ha il livello @Transacional sia nel livello di classe o un metodo

Seconda

Dov'è la classe che implementa WebApplicationInitializer? vedo si sta estendendo una classe .. Comunque il mio punto è, dove è qualcosa di simile al seguente:

@Override 
public void onStartup(ServletContext container) { 
    // Create the 'root' Spring application context 
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
    rootContext.register(CentralServerConfigurationEntryPoint.class); 

    // Manage the lifecycle of the root application context 
    container.addListener(new ContextLoaderListener(rootContext)); 

    // Create the dispatcher servlet's Spring application context 
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext(); 
    dispatcherServlet.register(CentralWebConfigurationEntryPoint.class); 

    // Register and map the dispatcher servlet 
    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet)); 
    dispatcher.setLoadOnStartup(1); 
    dispatcher.addMapping("/"); 

} 

Dove CentralServerConfigurationEntryPoint.class deve eseguire la scansione solo i componenti che devono lavorare nel lato server (@Service, @Repository, @Configuration per la transazione , Hibernate, ecc DataSource)

Dove CentralWebConfigurationEntryPoint deve eseguire la scansione solo i componenti che devono lavorare nel lato client/web (@Controller, @Configuration per Formattatori, piastrelle, convertitori ecc)

Non capisco il tuo codice su

@Override 
protected WebApplicationContext createRootApplicationContext() { 
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 

    ConfigurableEnvironment environment = rootContext.getEnvironment(); 
    environment.setDefaultProfiles("production"); 

    PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles()); 
    String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages"); 
    rootContext.scan(basePackages); 

    return rootContext; 
} 

@Override 
protected WebApplicationContext createServletApplicationContext() { 
    return new AnnotationConfigWebApplicationContext(); 
} 

Il mio punto è: voi must hanno due AnnotationConfigWebApplicationContext uno per il lato server e web.

+0

Ho aggiunto '@ Transactional 'a tutte le mie classi' @ Repository' e '@ Service' senza successo. Per dare un'occhiata a Spring JavaDocs: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/support/AbstractDispatcherServletInitializer.html – dtrunk

+0

Il mio approccio o configurazione è stata presa come fare riferimento agli Spring Samples offerti su Github dagli stessi Spring Developer. La prima volta che vedo il tuo approccio, solo curioso, qual è il tuo blog/tutorial in cui hai preso il tuo approccio? –

+0

Esempio: http://saltnlight5.blogspot.de/2013/10/getting-started-with-annotation-based.html Ci sono diversi tutorial in rete usando 'AbstractAnnotationConfigDispatcherServletInitializer' come super-classe. Ho esaminato il codice per capire che cosa stava succedendo lì e poi mi sono reso conto che l'uso di 'AbstractDispatcherServletInitializer' è decisamente migliore per il mio approccio, poiché voglio scansionare i pacchetti invece di aggiungerli direttamente. – dtrunk

Problemi correlati