首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EJB3事务传播

EJB3事务传播
EN

Stack Overflow用户
提问于 2008-09-19 23:43:08
回答 8查看 18.5K关注 0票数 26

我有一个无状态bean,类似于:

代码语言:javascript
复制
@Stateless
public class MyStatelessBean implements MyStatelessLocal, MyStatelessRemote {
    @PersistenceContext(unitName="myPC")
    private EntityManager mgr;

    @TransationAttribute(TransactionAttributeType.SUPPORTED)
    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.process(obj);
        }
    }

    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(Object obj) {
        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();
    }
}

通常的用法是客户端调用processObjects(.),它实际上不与实体管理器交互。它做它需要做的事情并调用进程(.)为每个对象单独处理。过程的持续时间(.)相对较短,但processObjects(.)可能要花很长时间才能完成所有的事情。因此,我不希望它维持一个开放的事务。我确实需要单独的程序(.)操作在自己的事务中操作。这应该是每一次呼叫的新事务。最后,我想让客户端调用进程(.)的选项保持开放。直接了当。

我尝试过许多不同的事务类型:从不,不支持,支持(在processObjects上)和必需,需要新的(在进程上),但是每次调用merge()时我都会得到TransactionRequiredException。

我已经能够通过将方法分成两个不同的bean来实现它:

代码语言:javascript
复制
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
    @EJB
    private MyStatelessBean2 myBean2;

    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.myBean2.process(obj);
        }
    }
}

@Stateless
public class MyStatelessBean2 implements MyStatelessLocal2, MyStatelessRemote2 {
    @PersistenceContext(unitName="myPC")
    private EntityManager mgr;

    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(Object obj) {
        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();
    }
}

但我仍然很好奇是否有可能在一节课上完成这个任务。在我看来,事务管理器只在bean级别运行,即使给单个方法提供了更具体的注释也是如此。因此,如果我标记一个方法来阻止事务开始调用同一实例中的其他方法,那么无论如何标记,也不会创建一个事务?

我使用的是JBoss应用服务器4.2.1.GA,但欢迎/首选非特定的答案。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-02-04 15:46:23

另一种方法是在同一个bean上使用这两种方法,并拥有对自身的@EJB引用!就像这样:

代码语言:javascript
复制
// supposing processObjects defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
    @EJB
    private MyStatelessLocal1 myBean2;

    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.myBean2.process(obj);
        }
    }


    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(Object obj) {
        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();
    }
}

通过这种方式,您实际上强制通过代理的ejb堆栈访问process()方法,从而使@TransactionAttribute生效,并且仍然只保留一个类。呼!

票数 24
EN

Stack Overflow用户

发布于 2010-04-17 22:06:24

马特,你问的问题是一个非常经典的问题,我认为赫瓦尔/帕斯卡的自我参照解决方案很好。这里没有提到更普遍的解决办法。

这是EJB“用户”事务的一个例子。因为您在会话bean中,所以您可以从会话上下文中获取用户事务。下面是您的代码如何处理用户事务:

代码语言:javascript
复制
// supposing processObjects defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {

    @Resource
    private SessionContext ctx;

    @EJB
    private MyStatelessLocal1 myBean2;

    public void processObjects(List<Object> objs) {
        // this method just processes the data; no need for a transaction
        for(Object obj : objs) {
            this.myBean2.process(obj);
        }
    }


    public void process(Object obj) {

        UserTransaction tx = ctx.getUserTransaction();

        tx.begin();

        // do some work with obj that must be in the scope of a transaction

        this.mgr.merge(obj);
        // ...
        this.mgr.merge(obj);
        // ...
        this.mgr.flush();

        tx.commit();
    }
}
票数 4
EN

Stack Overflow用户

发布于 2008-12-04 16:32:11

我认为问题是,每个bean都被包装在一个代理中,该代理控制事务行为。当您从一个bean调用到另一个bean时,您将通过该bean的代理进行调用,并且代理可以更改事务行为。

但是,当bean使用不同的事务属性调用自身上的方法时,调用不会通过代理进行,因此行为不会改变。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/106437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档