之前,我使用的是GlassFish v2ur1(這是我公司採用一個,我不能在這一點上升級)。我有一個EJB(ejbA)從定時器週期性地調用。在調用中,我正在讀取一個文件,爲每一行創建一個實體bean,並將實體bean持久化到一個db(PostgreSQL v9.2)。調用entitymanager.persist(EntityBean的)之後,HTTP調用是一個Servlet發出,傳遞的EntityBean的ID,進而調用到另一個EJB(ejbB)。 ejbB將JMS消息發送給另一個實體bean ejbC。這是一個生產系統,我必須進行HTTP調用,它會進一步處理數據。 ejbC與ejbA位於同一企業應用程序中,但使用不同的EntityManager。 ejbC收到id,從db中讀取記錄,修改記錄,並保存它。寫實體bean內容數據庫事務提交
我遇到的問題是實體Bean的數據不被存儲到數據庫,直到從計時器調用該交易完成後(見下文)(我的理解就是這樣EJB的工作)。當調用ejbB時,它無法用它收到的id在db中找到記錄。我試過幾個方法來獲得存儲在數據庫中的數據,從而EJBC可以找到它:
1)我嘗試設置沖洗模式ejbA堅持的EntityBean的時候COMMIT:
- em.setFlushMode(FlushModeType.COMMIT)
- instantiate entity bean
- em.persist(entityBean)
- em.flush()
但是,結果是相同的,到調用ejbC時,db中沒有記錄。
2)I創建ejbD並在其中添加了一個storeRecord方法(該方法仍然存在的EntityBean)與TransactionAttributeType.REQUIRES_NEW。這應該暫停ejbA的事務,啓動ejbD的事務,提交它並恢復ejbA的事務。同樣,這裏的結果是一樣的,到調用ejbC時,db中沒有記錄。我也看到這個解決方案的問題,當我調用storeRecord方法時,ejbA調用停止。沒有拋出異常,但我沒有看到EJB處理來自文件的更多行,即使有更多的行。它似乎中止了EJB調用,並且沒有任何跡象回滾事務。不確定這是否是GlassFish v2ur1錯誤。
如何確保數據被存儲到ejbA分貝,所以當EJBC被調用時,它可以找到在DB的記錄?順便說一句,還有其他事情在ejbA中進行,我不一定要提交。我想只堅持我想要存儲到數據庫的entityBeans。
ejbA
ejbTimer called (txn starts)
read file contents
for each line
create entity bean
persist entity bean to db
make HTTP call to ejbB, passing id
<see ejbC>
return (txn ends)
ejbB
Processes data based on id
Looks up JMS queue for ejbC
Passes ejbC the id
EJBC
ejb method called (txn starts)
read record based on received id
modify record and persist
return (txn ends)
格倫,謝謝你的迴應。我改變了我的代碼,將一個遠程接口添加到ejbB,ejbA現在調用(在持久化entityBean之後)而不是使用HTTP。但是,我看到的行爲是ejbB找不到entityBean ejbA持久化,因此它會創建一個新的。我給的例子被簡化了。 ejbA在堅持entityBean之後調用ejbB。但ejbB將JMS消息發送給另一個EJB,將其稱爲ejbD,ejbD執行entityBean的查找並創建一個新的,如果未找到。我不認爲這會改變任何事情,因爲它們仍然在同一個事務中執行。 –
最好是更新示例以包含ejbD和JMS,創建一個新問題,或者只是留下評論中的信息? –
如果ejbD由JMS調用(例如它是一個消息驅動的bean),那麼ejbD將不會在與ejbB相同的事務中運行。它可能會在ejbB完成之前運行。這聽起來像ejbD正在做的工作應該直接調用,而不是通過JMS延期。 –