确保JPA在其他服务访问数据之前提交我的交易 [英] Making sure JPA commits my transaction before another service accesses the data

查看:116
本文介绍了确保JPA在其他服务访问数据之前提交我的交易的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感觉很简单:

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

I have a ViewScoped bean (JPA2 + EE6 + Seam3, if that matters) where the user of the web application can invoke a method like this:

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

不幸的是,save()在左花括号处开始事务,并且在右花括号前不提交事务,这意味着新数据不可用于远程Web服务读取.

Unfortunately, save() starts a transaction at the opening curly bracket and doesn't commit it before the closing bracket, meaning that the new data is not available to the remote web service to read.

我试图显式提取和注释数据库工作:

I have tried to explicitly extract and annotate the database work:

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

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

But that didn't have any impact at all. (Maybe because that's EJB stuff and I'm running on seam...?)

到目前为止,对我而言唯一有效的方法是注入@UserTransaction并在save()doEntityManagerStuff()的末尾强制执行事务,但是这确实令人难以置信且危险.

The only thing that worked for me so far was to inject @UserTransaction and force commit the transaction at the end of either save() or doEntityManagerStuff() but that felt incredibly dirty and dangerous.

另一种选择是关闭整个项目的容器管理的事务,但这意味着我必须让 all 我的bean手动管理事务, just ,这样我就可以解决这个问题了.

The other alternative would be to turn off container-managed transactions for the entire project, but that means I'd have to make all my beans manage their transactions manually, just so I can make this one case work.

有更好的方法吗?

推荐答案

要回答我自己的问题:

我只走了一半,这就是为什么它不起作用的原因.我对EJB及其它们的知识还不甚了解,并且天真地尽管只在我的作用域范围内的CDI/Seam bean中用事务属性注释doEntityManagerStuff(...)方法就足够了.

I only went half-way, and that's why it didn't work. I didn't know enough about EJBs and their boudaries, and naively though just annotating the doEntityManagerStuff(...) method with a transaction attribute in my view-scoped CDI/Seam bean would be enough.

不是.

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

When I moved said method into a separate, stateless EJB, injected that into my CDI/Seam bean and called it from there, everything worked as expected.

@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();
    }

    ...
}

这篇关于确保JPA在其他服务访问数据之前提交我的交易的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆