[英]Open new transaction when already inside ejb
請考慮以下情況:
@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
}
}
從ejb外部調用方法foo。 我希望每個id在自己的事務中執行,以便數據直接保存到數據庫中。 此類之外的foreach是不可能的。 我想知道什么是最好的方法嗎? 此刻,我再次注入接口,以跨過ejb邊界(以便對TransactionAttribute進行評估)。
您關於循環參考的方法非常好。 允許在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
,從而加快任務的執行速度。
您真的必須在一個類中同時使用這兩種方法嗎? 您可以將bar()
移到自己的bean上並使其具有事務性。 然后,您不必使用這種自我注入。
您也可以嘗試使用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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.