Making sure JPA commits my transaction before another service accesses the data

[亡魂溺海] 提交于 2019-12-25 03:34:22

问题


It feels so simple:

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
}

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
}

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

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.

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.

Is there a better way?


回答1:


To answer my own question:

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.

It isn't.

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
    }

    ...
}

and

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

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

    ...
}


来源:https://stackoverflow.com/questions/30405281/making-sure-jpa-commits-my-transaction-before-another-service-accesses-the-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!