2013-10-01 98 views
1

我正在使用JBoss EAP 6.1.0和EJB/JPA。我有幾個組的用戶對象,他是屬於我試圖用三步法在數據庫中創建此:JPA事務:提交後選擇正確?

  1. 保存用戶
  2. 保存他屬於
  3. 查詢組數據庫並返回新的用戶

我的問題是,步驟(3)總是返回null,因爲提交尚未發生。在步驟2和步驟3之間添加em.flush()不會有幫助。我避免使用任何@CASCADE批註,因此只保存用戶並讓羣組級聯不是一個選項。下面是示例代碼:

@Stateless 
public class RegistrationService { 

    @EJB 
    UserDao userDao; 

    public User registerNewUser(User user, List<Group> groups) { 
     userDao.saveNewUser(user); 
     userDao.saveNewGroupsToUser(user, groups); 
     return userDao.findUser(user); 
    } 
} 

這裏是一個簡化的UserDAO:

@Stateless 
public class UserDao { 

    @PersistenceContext 
    private EntityManager em; 

    public void saveNewUser(User user) { 
    em.persist(user); 
    } 

    public void saveNewGroupsToUser(User user, List<Group> groups) { 
    for (Group group : groups) { 
     GroupToUser groupToUser = new GroupToUser(user, group); 
     em.persist(groupToUser); 
    } 

    public User findUser(User user) { 
    return em.createQuery("from User where user = :userId") 
     .setParameter("userId",user.getUserId()) 
     .getSingleResult(); 
    } 
} 

什麼我發現是,如果我註釋findUser(User)方法與@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)它按預期工作。這是爲什麼呢?我認爲registerNewUser()創建了一個大事務,然後findUser()會創建一個嵌套的事務,它不應該知道有關的存儲呢?

回答

0

我最終在findUser()方法上使用了@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)。由於容器管理事務(CMT)不允許嵌套事務,因此這似乎會刷新先前的SQL更新/插入語句,從而允許select按預期工作。

2

我想你應該在步驟1(保存用戶之後)後添加em.flush(),因爲它將執行保存新用戶的SQL。

第二件事,從代碼看來,使用容器管理的事務。 CMT不允許嵌套事務。所以基本上添加REUIRED_NEW屬性可能會強制刷新以前的保存SQL查詢。確認這一點的一種方法是記錄SQL查詢

+0

保存後的em.flush()似乎沒有效果,我仍然回到空。我會繼續調查。 – Strumbles

+0

我想我會堅持使用'findTransactionAttribute(TransactionAttributeType.REQUIRES_NEW)'在'findUser()'方法,因爲這樣做的竅門。由於我使用CMT,這可能是我能得到的最好的。 – Strumbles