2012-08-16 57 views
4

我繼承了一些代碼,當試圖添加一些功能時,不適合我。我不是Java網絡的專家,所以如果我需要任何額外的手持功能來爲您提供所需的信息,我很抱歉。交易在碼頭不堅持時間

我正在開發一個GWT應用程序,它在後端使用Hibernate和Guice-Persist來堅持MySQL。不幸的是,我遇到了一個奇怪的問題,在這個問題中 - 在一臺服務器上 - put事務沒有及時保存到數據庫中,以便後續的get事務處理。 在任何版本的Jetty中嵌入GWT Eclipse插件(可能是6.1.11?)在Windows和Linux中的Tomcat6中都能正常工作,但是當我嘗試在Linux中使用jetty-maven-plugin版本8.1.0(也在8.1.5中只有兩個版本我試過),我遇到這個問題,交易沒有及時完成。(或者,我會很高興能找到一個解決方案,讓我可以在Maven中使用除Jetty以外的其他方法正確運行我的集成測試,從而避免了這個問題。已經嘗試過)。

下面是我用堅持一個對象的代碼:

public T put(T entity) { 
    EntityManager entityManager = entityManager(); 
    EntityTransaction transaction = entityManager.getTransaction();   
    transaction.begin(); 
    try { 
     entity = entityManager.merge(entity); 
     entityManager.persist(entity); 
     transaction.commit(); 

    } catch (Exception e) { 
     //do exception handling, including rollback 
    } 


    return entity; 
} 

的GET代碼:

public List<T> getAll() { 
    Query query = entityManager().createQuery("select c from " + clazz.getSimpleName() + " c"); 

    return (List<T>) query.getResultList(); 
} 

同樣,發生的事情是我做的(間接)調用getAll()以允許客戶端查看數據。然後,如果他們做出選擇,請從客戶端撥打電話put。然後,一旦我收到回覆,撥打getAll()即可更新顯示給用戶的數據。不幸的是,我從數據庫中得到的數據並不反映更新的數據,而是數據,因爲它存在於put()調用之前。數據庫最終會更新,當我自己檢查數據庫時,它似乎會立即更新。如果我重新加載數據幾次,Web應用程序也將最終更新以顯示正確的數據。所以我懷疑有些緩存層可能會響應我的getAll()請求而沒有真正檢查數據庫,但我真的不知道如何繼續 - Transactions和EntityManagers對我來說是相當新的。

我試過flush() ing和close() ing我的實體管理器,而不是提交我的交易,並沒有任何行爲改變。

我注射在構造函數中我的EntityManager提供者:

private final Class<T> clazz; 
private final Provider<EntityManager> entityManagerProvider; 

public BaseDao(final Class<T> clazz, final Provider<EntityManager> entityManagerProvider) { 
    this.clazz = clazz; 
    this.entityManagerProvider = entityManagerProvider; 
} 

,卻得到了實體管理器,像這樣:

protected EntityManager entityManager() { 
    return entityManagerProvider.get(); 
} 

謝謝!

爲後人的緣故,這裏是我的GuiceServletContextListener:

public class GuiceServletConfig extends GuiceServletContextListener { 
@Override 
protected Injector getInjector() { 
    DispatchServletModule dispatchServletModule = new DispatchServletModule(); 
    Injector injector = Guice.createInjector(new ServerModule(), new JpaPersistModule(getPersistenceUnit()), 
      dispatchServletModule); 

    PersistService persistService = injector.getInstance(PersistService.class); 
    persistService.start(); 

    BootStrapper bootStrapper = injector.getInstance(BootStrapper.class); 
    bootStrapper.init(); 



    return injector; 
} 

private String getPersistenceUnit() { 
    InputStream inputStream = getClass().getResourceAsStream("/database.properties"); 

    if (inputStream == null) { 
     throw new RuntimeException(); 
    } 

    try { 
     Properties properties = new Properties(); 
     properties.load(inputStream); 

     return properties.getProperty("persistenceUnit"); 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } 
} 


} 

而且我的servlet:

public class DispatchServletModule extends ServletModule {  
    @Override 
    public void configureServlets() { 
    serve("/" + ActionImpl.DEFAULT_SERVICE_NAME + "*").with(DispatchServiceImpl.class); 
    } 
} 

我嘗試添加在configureServlets過濾器(),而在手動啓動的持續性會話嘗試使用session-per-http請求(每this page),但沒有運氣。

+5

那麼,你應該給我們在所有... – Baz 2012-08-16 13:27:11

+0

商定的任何信息開始.. 。按下輸入標籤時輸入太快。我的錯。給我一點時間... – 2012-08-16 13:27:39

+1

只是好奇心:什麼是調試輸出告訴你?通常你應該看到執行的SQL。你確定**它沒有拋出一個你只是捕獲並默默忽略的異常? – PepperBob 2012-08-23 17:42:30

回答

0

首先,您應該回滾catch塊中的交易,而不是忽略異常(至少記錄它)。但guice-persist支持@Transactional註釋,所以實際上你根本不需要手動進行事務管理。見Transactions - google-guice

+0

謝謝。在「異常處理」中隱藏的實際上是一個'rollback()'調用。我會調查你提到的那個鏈接。 – 2012-08-16 13:44:18

+1

只是爲了確保我理解您的意見......您是否在暗示'@ Transactional'註釋會改變代碼的行爲並解決問題?或者更容易維護? UnitOfWork系統的推出有助於確保我的數據及時寫回來嗎? – 2012-08-16 13:48:53

+0

@Jeff:我不確定它會解決你的問題,但當你讓圖書館爲你做時,以正確的方式做事情總是更容易。請注意,雖然'@ Transactional'需要位於由Guice注入的類的方法中。 – 2012-08-16 16:30:57

0

您是否希望關閉與交易相關的會話?

public T put(T entity) { 
    EntityManager entityManager = entityManager(); 
    EntityTransaction transaction = entityManager.getTransaction();   
    transaction.begin(); 
    try { 
     entity = entityManager.merge(entity); 
     entityManager.persist(entity); 
     transaction.commit(); 

    } catch (Exception e) { 
     //do exception handling, including rollback 
    } finally { 
     entityManager.close(); 
    } 

    return entity; 
} 

但你可以強制交易與沖洗同步:

public T put(T entity) { 
    EntityManager entityManager = entityManager(); 
    EntityTransaction transaction = entityManager.getTransaction();   
    transaction.begin(); 
    try { 
     entity = entityManager.merge(entity); 
     entityManager.persist(entity); 
     entityManager.flush(); 
     transaction.commit(); 

    } catch (Exception e) { 
     //do exception handling, including rollback 
    } 

    return entity; 
} 

問候,

+0

沒有運氣,但我認爲我們可能會朝着正確的方向前進......我的一個'put()'調用中出現了'EntityManager已關閉'的錯誤 - 它看起來像我的提供程序 '正在返回使用EntityManagers的實例,而不是將它們扔掉並製作新的實例。我應該創建我的EntityManagers有不同的方式嗎? – 2012-08-24 13:26:02

+0

它可以是有用的以下鏈接:http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/ – 2012-08-24 13:37:57

+0

你可以更具體的鏈接?我沒有看到任何直接用於解決問題的方法。在發現EntityManager被回收之後,我意識到可能在返回之前clear()entityManager可能會解決其中的一些問題。事實上,它現在更加穩定,但我必須在每個函數的末尾手動清除每個EntityManager。關於如何使用這個的任何想法? – 2012-08-24 15:09:59