2012-12-21 174 views
4

我要求如下:Hibernate Sessionfactory restart |春天

我需要重新啓動(或重建)在與新的HBM文件,我從外面得到頻繁的時間間隔在我的春天web應用程序Hibernate會話工廠。

目前我的Sessionfactory類如下所示,用SessionFactory代理攔截「OpenSession」調用。

在那裏我正在檢查一個條件來重新啓動並重建sessionFactory。

這裏我的問題是,在併發環境中,處於其他事務中間的其他用戶在此重新啓動期間受到影響。

有沒有辦法通過檢查所有事務並打開會話來執行重新啓動,並在所有其他事務完成後執行重建會話工廠?

或存在任何其他解決方案。

代碼:

public class DataStoreSessionFactory extends LocalSessionFactoryBean 
{ 


    private boolean restartFactory = false; 



    @Override 
    protected void postProcessConfiguration(Configuration config) throws HibernateException 
    { 
     super.postProcessConfiguration(config); 
     updateHBMList(config); 
    } 


    private void updateHBMList(final Configuration config) 
    { 

     config.addXML(modelRegistry.generateMapping()); 
    } 

    @Override 
    public SessionFactory getObject() 
    { 

     Object obj = super.getObject(); 

     /* 
     * Invocation handler for the proxy 
     */ 
     SessionFactoryProxy proxy = new SessionFactoryProxy(this, (SessionFactory) obj); 

     /** 
     * All the methods invoked on the returned session factory object will pass through this proxy's invocation 
     * handler 
     */ 
     SessionFactory sessionFactory = (SessionFactory) Proxy.newProxyInstance(getClass().getClassLoader(), 
                       new Class[] { SessionFactory.class }, 
                       proxy); 
     return sessionFactory; 
    } 

    static class SessionFactoryProxy implements InvocationHandler 
    { 


     private SessionFactory sessionFactory; 

     private LocalSessionFactoryBean factoryBean; 

     public SessionFactoryProxy(LocalSessionFactoryBean factoryBean, SessionFactory sessionFactory) 
     { 
     this.factoryBean = factoryBean; 
     this.sessionFactory = sessionFactory; 
     } 

     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
     { 
     /** 
      * Only if the method invoked is openSession - check if the session factory should be restarted, and only then 
      * invoke the requested method 
      */ 
     if (method.getName().equals("openSession")) 
     { 
      restartSessionFactoryIfNecessary(); 
     } 
     return method.invoke(sessionFactory, args); 
     } 

     private void restartSessionFactoryIfNecessary() 
     { 
     restartSessionFactory(); 
     /*if (((DataStoreSessionFactory) factoryBean).isRestartFactory()) 
     { 
      restartSessionFactory(); 
     }*/ 
     } 

     private synchronized void restartSessionFactory() 
     { 
     log.info("Restarting session..."); 
     factoryBean.destroy(); 
     try 
     { 
      factoryBean.afterPropertiesSet(); 
      sessionFactory = factoryBean.getObject(); 
     } 
     catch (Exception e) 
     { 
      log.error("Error while restarting session: " + e.getMessage()); 
      throw new RuntimeException(e); 
     } 
     } 
    } 

感謝, Appasamy

+0

爲什麼不在非辦公時間重建會議工廠? –

+0

Ouch,這是你的應用程序必須具備的一些令人討厭的設計/架構。在運行時改變休眠/數據庫配置並不美觀... – pap

回答

2

您可以按照SessionFactoryUtils中,以確定交易是否發生在Session的工廠,然後決定重新啓動會話工廠與否: 你會需要導入 - > org.springframework.orm.hibernate.SessionFactoryUtils在你的文件中,並使用下面的API。

static boolean hasTransactionalSession(SessionFactory sessionFactory); 

以上API返回是否有交易的Hibernate Session當前線程,也就是由Spring的事務facilities.There綁定到當前線程會話也是以防萬一,如果你需要檢查另一個API如果會話是事務在當前會話工廠:

static boolean isSessionTransactional(Session session,SessionFactory sessionFactory); 

以上API返回是否給定的特定Hibernate的Session是事務性的,也就是說,綁定到Spring的事務設施當前線程。

相關問題