考虑以下情况:
@Stateless
@Clustered
public class FacadeBean implements Facade {
@EJB
private Facade facade;
@Override
public void foo(List<Integer> ids) {
// read specific id's from the db
for (Integer id : ids) {
facade.bar(id);
}
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void bar(Integer id) {
// save something to the db
}
}
方法foo从ejb外部调用。我希望每个id都在自己的事务中执行,这样数据get就会直接保存到数据库中。在本课程之外不可能有foreach。我想知道最好的方法是什么?目前我再次注入接口,跨越ejb边界(以便对TransactionAttribute get进行评估)。
答案 0 :(得分:1)
关于循环引用的方法非常好。允许在EJB中使用循环引用。这甚至是强制性的,以便开始新的事务或@Asynchronous
线程(否则当前线程仍会阻塞)。
@Stateless
public class SomeService {
@EJB
private SomeService self; // Self-reference is perfectly fine.
// Below example starts a new transaction for each item.
public void foo(Iterable<Long> ids) {
for (Long id : ids) {
self.fooInNewTransaction(id);
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void fooInNewTransaction(Long id) {
// ...
}
// Below example fires an async thread in new transaction.
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void bar(Iterable<Long> ids) {
for (Long id : ids) {
self.fooAsynchronously(id);
}
}
@Asynchronous
public void fooAsynchronously(Long id) {
// ...
}
}
仅在较旧的容器中,这不起作用,最值得注意的是具有古老EJB 3.0 API的JBoss AS 5。这就是为什么人们发明了SessionContext#getBusinessObject()
之类的解决方法,甚至是通过JNDI手动抓取的原因。
这些天不需要这些。这些是变通办法而非解决方案。
我个人只是在交易方面做了相反的事情。 foo()
方法显然从不打算成为交易方式。
@Stateless
public class SomeService {
@EJB
private SomeService self;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void foo(Iterable<Long> ids) {
for (Long id : ids) {
self.foo(id);
}
}
public void foo(Long id) {
// ...
}
}
根据具体的功能要求,您甚至可以制作foo(Long id)
@Asynchronous
,从而加快完成任务。
答案 1 :(得分:0)
你真的必须在一个班级中拥有这两种方法吗?您可以将bar()
移动到自己的bean并使其成为事务性的。然后你不必使用这种自我注射。
答案 2 :(得分:-2)
您也可以尝试使用SessionContext#getBusinessObject()
方法。
@Resource
SessionContext sessionContext;
@Override
public void foo(List<Integer> ids) {
Facade facade = sessionContext.getBusinessObject(Facade.class);
// read specific id's from the db
for (Integer id : ids) {
facade.bar(id);
}
}