2012-08-13 31 views
1

我正在用JBoss 7.1.1 Final,Weld,Hibernate 4,Seam 3進行開發,我不明白以下行爲。我使用Seam管理的持久化上下文的實體管理器和持久性攔截煤層3.我有以下CDI豆:FlushMode type Commit與REQUIRES_NEW一起使用Transaction屬性

@ViewScoped 
@Named 
public class RegistrationController implements Serializable { 

    @Inject 
    private RegisterService service; 

    @Inject 
    private EntityManager em; 

    public void register() { 
      Person p = service.register("username","password"); 
      Person pp = em.find(Person.class, p.getId()); //returns null 
    } 
} 

而繼EJB

@Stateless 
@Local(IRegisterService.class) 
public RegisterService implements IRegisterService { 

     @Inject 
     private EntityManager em;  

     @Override 
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
     public Person register(String username, String password) { 
      return em.merge(new Person(username, password)); 
     } 
} 

所以,因爲我使用Seam持久性模塊我以爲這將發生的操作的流程:

1)registrationController.register()是從前端稱爲

2)新事務A開始

3)service.register(...)被調用

4)事務A被暫停,並且用於service.register的執行(因爲它是由REQUIRES_NEW註釋)被創建事務B

5 )執行service.register(...)完成

6)事務B致力於

7)由於我使用COMMIT沖洗型,沖洗將被稱爲

8)交易A被打開回來

現在,em.find(Person.class,p.getId())正試圖找到持久的人。由於事務B已提交併且實體管理器已刷新,因此應該找到它。但它返回null。如果我手動刷新,那麼它工作。

我在哪裏犯錯?有一些誤解嗎?

+0

你有沒有調試交易?例如,如果您使用的是log4J,則使用'log4j.logger.org.jboss.seam.transaction = DEBUG'。 – 2012-08-16 15:24:03

回答

0

從看你的代碼我會說 - 因爲RegistrationController是一個普通的託管bean - 它會不是開始自己的交易。這基本上意味着你有一個單一的交易B.

+0

,但在調用託管bean中的em.find(Person.class,p.getId())之前,它仍然應該提交(並因此刷新)。此外,我使用Seam 3的持久化模塊,所以事實上即使在託管bean中自動啓動事務。 – lukas 2012-08-14 05:54:36

+0

我明白了。嗯。我仍然認爲問題來自意外的事務行爲 - 我依稀記得事務邊界有專門的日誌記錄選項 - 這應該帶你更進一步...... – 2012-08-14 06:42:22

+0

看來,如果我在服務(EJB)中使用SMPC,它不起作用,但如果我使用@PersistenceContext來獲取我的entitymanager,它工作正常。我不明白這種行爲。 – lukas 2012-08-14 15:34:46

相關問題