gpt4 book ai didi

Java EE 7 - 如何从容器内部启动事务?

转载 作者:行者123 更新时间:2023-12-02 01:33:12 24 4
gpt4 key购买 nike

我正在使用 Java EE 7 + GlassFish,需要对无状态 bean 中的多个 JPA 实体执行一些操作。

@Stateless
public class JobRunner
{
public void do()
{
for (Entity entity:facade.findAll())
{
///do some work against entity
}
}
}

这个 JobRunner bean 被注入(inject)到 servlet 中,我从 Web UI 调用 do() 方法。

问题是所有实体都在一个事务中发生更改,因此如果一个事务失败,所有实体都会回滚,这是不希望的。有没有办法为每个实体(即循环的每次迭代)启动和关闭新事务?

我可以编写一个外部客户端并在其中创建一个循环,为每个实体调用无状态 bean,但这并不是完全适合我的东西,因为我更喜欢保持应用程序整体化。我可以以某种方式管理容器内的事务表单吗?

也许 JMS 有帮助?如果我实现一个执行者作为消息监听器并将为每个实体发送一条消息,它会为每个实体启动一个新事务吗?

@Stateless
public class JobRunner
{
public void do()
{
for (Entity entity:facade.findAll())
{
sendMessageToRealDoer(entity);
}
}
}

最佳答案

创建另一个bean,在方法或bean级别指定@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW):

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
public class JobWork {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void doWork(Entity entity) {
// do what you would do in the loop with the Entity
// this runs in a new transaction
}
}

我希望我能告诉您,您只需要注释同一个 bean (JobRunner) 的方法并简单地调用它。这是不可能的(编辑)没有解决方法 - 检查 Steve C 的评论(/编辑),因为在 EJB 和 CDI bean 中调用 this 对象的方法时,拦截器不会获取叫。在这两种情况下,事务都是通过拦截器实现的。

一些注意事项:

  • 如果循环中操作的总持续时间预计很长,您将在 外部 事务中遇到超时,该超时是为 JobRunner 隐式启动的无状态 EJB。您需要采取措施确保不启动任何“外部”事务。
  • 将数据发送到队列也可以;但队列会异步处理它们,这意味着执行很可能会在处理所有项目之前返回到调用 JobRunner.do() 的 servlet。

关于Java EE 7 - 如何从容器内部启动事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55698022/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com