2014-02-09 224 views
0

這裏是我所得到的:爲什麼在參數中沒有保存輸出參數?

public User register(User u) { 
    em.persist(u); 
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 0 
    em.flush(); 
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 1 
    return u; 
} 

即使我省略了調用flush()儘管用戶堅持在DB(MySQL的,我用glasssfish 4從日食)。那麼爲什麼我需要調用flush來設置id(它在方法出口時顯然是自動調用的,但是說我想在register()中使用該id)?

順便說一句,flush()被調用的事實表明事務正在進行嗎?

更新:這裏的EJB類:

@Stateless 
public class UserService { 

    @PersistenceContext 
    private EntityManager em; 

    public User register(User u) { 
     em.persist(u); 
     // em.flush(); // not needed - called on exit - maybe I have a 
     // transaction after all 
     return u; 
    } 
} 
+0

UserService從'@ManagedBean @ViewScoped public class UserController {@EJB private UserService service; }'。我終於猜測題目問題的答案是persist()需要是異步的。 –

回答

0

如果檢查the documentation for EntityManager你可以看到。

空隙沖洗()

同步持久上下文到底層數據庫。

Persist()不會刷新您的實體,但它會對數據庫執行操作。

要獲得您的ID,您必須同步您的實體。

AFAIR flush()與交易無關。由於JTA管理您的交易。 JTA調用由EntityManager.getTransaction()返回的EntityTransaction的方法begin,commit,rollback。

如果您在實體上調用EntityManager.refresh方法,它也應該同步。

編輯

每個EJB由Java EE容器管理。您剛剛注意到這種管理的效果。每個方法調用都處於事務中,也可能與此同步有關。

要知道爲什麼它的發生,你可以撥打:

Thread.currentThread().getStackTrace() 

在你UserService.register,並打印堆棧跟蹤元素的全陣列。您將得到類似於:

UserService.register(UserService.java:xxx) 
SomeGenerated.invoke(SomeGenerated.java:xxx) 
SomeGenerated.invoke(SomeGenerated.java:xxx) 
UserController.register(UserController.java:xxx) 

所以,你不直接從UserController.register,你也許希望調用UserService.register方法。

這個「SomeGenerated」類負責處理給你EJB的合同。例如,他們關心交易,也可能在您的情況下關於使用數據庫同步實體。

+0

如果我只是'em.persist(u);返回u;'u'我得到的是正確的id - 所以在方法返回時調用flush或refresh。我用我的類的註釋編輯了問題 - 我在'UserService .register()'上運行事務嗎? (雖然我的問題是_why_堅持不刷新我會滿意_how_ :) –

+0

我已更新帖子回答你的問題 – zimi

+0

謝謝 - 我已經看到堆棧跟蹤和\ _ \ _生成\ _而不必調用' Thread.currentThread()。getStackTrace()'(笑話),但你的回答是有道理的:)。爲了完美,我希望有一些鏈接指向這個同步的文檔。 @stateless是否對交易產生影響? –

相關問題