2011-06-16 60 views
3

我在问我应该如何处理后台线程在我的Hibernate/Spring Web应用程序中执行涉及数据库的任务。如何处理Hibernate/Spring应用程序中的后台线程

目前我正在使用下面的拦截器,所以我可以用@OpenSession注释我的线程运行方法,应该打开一个会话。这也应该适用于RMI请求,例如或者在没有打开会话的情况下调用的任何其他方法。但是,我不确定代码是否正确,我面临的问题是有时会话只是没有关闭并且永远打开。

@Around("@annotation(openSession)") 
    public Object processAround(ProceedingJoinPoint pjp, OpenSession openSession) throws Throwable { 

     boolean boundResource = false; 
     Session session = null; 

     // Bind the session to the thread, if not already done 
     if(TransactionSynchronizationManager.getResource(sessionFactory) == null) { 
      log.debug("Opening Hibernate Session in method "+pjp.getSignature()); 

      session = SessionFactoryUtils.getSession(sessionFactory, true); 
      TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); 
      boundResource = true; 
     } 

     // Invoke the annotated method 
     Object ret; 
     try { 
      ret = pjp.proceed(); 
     } 
     catch(Throwable t) { 
      // Rethrows the Exception but makes sure the session will be closed 
      SessionFactoryUtils.closeSession(session); 
      log.debug("Closing Hibernate Session in method (Exception thrown) "+pjp.getSignature()); 
      throw t; 
     } 

     // If a resourc was bound by this method call, unbind it. 
     if(boundResource) { 
      //SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory); 
      session.flush(); 
      SessionFactoryUtils.closeSession(session); 

      log.debug("Closing Hibernate Session in method "+pjp.getSignature()); 
     } 

     return ret; 
    } 
+1

你为什么需要它?你不能只使用'@ Transactional'吗? – axtavt 2011-06-16 16:53:54

+0

这会为我打开一个会话吗?如果会话已经存在会发生什么? – Erik 2011-06-16 16:56:52

+0

据我了解,它基本上与你的代码完全一样。 – axtavt 2011-06-16 17:06:02

回答

1

是的,你建议的解决方案应该工作(我自己做了一些非常类似的事情)。如果您只使用@Transactional,那么对于每个事务,您将得到一个新的EntityManager,如果您的后台线程有很多事务,则这不一定是最佳的。

1

Hibernate会话和JDBC连接不是线程安全的。您应该坚持每个线程的连接和会话。

相关问题