2012-08-13 33 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

相关问题