在同一EJB内调用方法时的事务传播

问题描述 投票:0回答:2

我有一个简单的EJB无状态类,有两个方法,都没有@TransactionAttribute。第一个方法保存啤酒,然后调用另一个方法,保存另一个啤酒,并引发异常。

@Stateless
public class EJBContainer {

    @PersistenceContext
    EntityManager em;

    public void testTransaction() {
        em.persist(getBeer("Corona"));
        try {
            saveAndThrowException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void saveAndThrowException() {
        em.persist(getBeer("Heineken"));
        throw new RuntimeException();
    }

    //getBeer() definition
}

我假设这两种方法都将使用默认事务类型(必填)-因此,将在第一种方法中创建一个新事务,并在第二种方法中使用它。因此,引发异常应回滚此事务,并且EntityManager不会保存任何啤酒。但事实证明,两种啤酒都已保存。我在哪里错了?

[当我将第二种方法移到另一个无状态EJB时,它按预期的方式工作-第一个EJB创建了新事务,第二个EJB使用了它,异常导致回滚,并且没有保存任何啤酒。

从此JAX-RS客户端调用EJB:

@ApplicationScoped 
public class BeerController { 

    @Inject 
    private EJBContainer ejbContainer; 

    @POST 
    public void addBeer() { 
        ejbContainer.testTransaction(); 
    } 
}
jakarta-ee transactions jax-rs ejb
2个回答
1
投票

由于您使用的是无界面视图,可能是注射无法正常工作。我会尝试使用@EJB注释而不是@Inject

@EJB 
private EJBContainer ejbContainer; 

@POST 
public void addBeer() { 
    ejbContainer.testTransaction(); 
}

这样,您应该获得预期的结果。但是您的一种假设并不完全正确。当您从saveAndThrowException调用testTransacion不是EJB调用时,这只是一个本地方法调用,如果您为@TransactionAttribute声明了不同的saveAndThrowException则无关紧要。

如果需要从EJB的另一个事务方法调用事务方法,则可以添加对EJB本身的引用,然后像调用另一个EJB一样进行调用:

@Stateless
public class EJBContainer {

    @PersistenceContext
    EntityManager em;

    @EJB
    private EJBContainer ejbContainer;

    public void testTransaction() {
        em.persist(getBeer("Corona"));
        try {
            ejbContainer.saveAndThrowException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void saveAndThrowException() {
        em.persist(getBeer("Heineken"));
        throw new RuntimeException();
    }

    //getBeer() definition
}

1
投票

无法发表评论,信誉不足。因此,有单独的帖子。

Areus的观点。调用的方式只是本地调用,因此,从外部调用时,在saveAndThrowException周围执行的所有拦截器都会被应用程序服务器省略。在将控制权返回给应用程序服务器之前,引发异常并直接捕获它。应用程序服务器对异常一无所知,因此,ergo erverything很好,并且事务已提交。

© www.soinside.com 2019 - 2024. All rights reserved.