确保JPA在另一个服务访问数据之前提交我的事务

时间:2015-05-22 20:20:40

标签: jpa jsf-2 transactions jta

感觉很简单:

我有一个ViewScoped bean(JPA2 + EE6 + Seam3,如果这很重要),Web应用程序的用户可以调用这样的方法:

public void save() {
    doEntityManagerStuff(); // manipulates data in the database
    callRemoteWebservice(); // which is to read said data and propagate it to other systems
}

不幸的是,save()在开始大括号开始一个事务,而在结束括号之前没有提交它,这意味着远程Web服务无法使用新数据读取。

我试图明确地提取和注释数据库工作:

@TransactionAttribute(REQUIRES_NEW)
private void doEntityManagerStuff() {
    blabla(); // database stuff
}

但这根本没有任何影响。 (也许是因为那是EJB的东西,而我正在接缝......?)

到目前为止,对我来说唯一有效的方法是注入@UserTransaction并强制在save()doEntityManagerStuff()结束时提交交易,但这感觉非常脏和危险。 / p>

另一种选择是关闭整个项目的容器管理事务,但这意味着我必须让所有我的bean手动管理他们的事务,只是所以我可以让这个案例有效。

有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

回答我自己的问题:

我只走了一半,这就是为什么它不起作用。我对EJB及其boudaries不太了解,虽然只是在我的视图范围的CDI / Seam bean中使用事务属性注释doEntityManagerStuff(...)方法就足够了。

不是。

当我将所述方法移动到一个单独的无状态EJB 中时,将其注入我的CDI / Seam bean并从那里调用它,一切都按预期工作。

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyPersister {
    ...

    public void doEntityManagerStuff() {
        blabla(); // database stuff
    }

    ...
}

@ViewScoped
public class MyWebsiteBean {
    ...
    @Inject MyPersister persister;
    ...

    public void save() {
        persister.doEntityManagerStuff(); //uses its own transaction
        callRemoteWebService();
    }

    ...
}