[英]Spring hibernate transactions propagations aren't working properly
我的項目中有一個事務類,它使用以下2種方法:
@Repository(value = "usersDao")
@Transactional(propagation = Propagation.REQUIRED)
public class UsersDaoImpl implements UsersDao {
@Autowired
SessionFactory sessionFactory;
/* some methods here... */
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW,readOnly = false,rollbackFor = {Exception.class})
public void pay(Users payer, int money) throws Exception {
if( payer.getMoney() < money ) {
throw new Exception("");
}
payer.setMoney(payer.getMoney()-money);
this.sessionFactory.getCurrentSession().update(payer);
}
@Override
@Transactional(readOnly = false,rollbackFor = {Exception.class})
public void makeTransfer(Users from, Users to, int money) throws Exception {
System.out.println("Attempting to make a transfer from " + from.getName() + " to " + to.getName() + "... sending "+ money +"$");
to.setMoney(to.getMoney()+money);
if( from.getMoney() < 10 ) {
throw new Exception("");
}
pay(from, 10);
if( from.getMoney() < money ) {
throw new Exception("");
}
from.setMoney(from.getMoney()-money);
this.sessionFactory.getCurrentSession().update(from);
this.sessionFactory.getCurrentSession().update(to);
}
}
假設有人進行轉帳時,他們必須支付10美元的稅。 假設有兩個同時擁有100 $的用戶,我想進行95 $的轉移(User1-> User2)。 首先在makeTransfer
,檢查User1是否能夠繳稅。 他是,所以我要繼續前進,檢查他是否還有95美元可以轉賬。 他沒有,所以交易被回滾了。 問題是,最后他們倆都有100 $。 為什么? 對於方法pay
我設置了Propagation.REQUIRES_NEW
,這意味着它在單獨的事務中執行。 那為什么還回滾呢? 實際應將稅款保存到數據庫中,並且僅應轉回轉帳。 對我而言,這樣做的全部目的是理解傳播。 我從理論上理解他們,但是無法做到一個真實的例子(傳播變化如何影響我的項目)。 如果這個例子令人誤解,我希望再看看一個例子。
迪努姆先生說了什么。
此外,根據Spring文檔:
如果希望自調用也與事務一起包裝,請考慮使用AspectJ模式(請參見下表中的mode屬性)。 在這種情況下,首先將沒有代理。 相反,將對目標類進行編織(即,將修改其字節碼),以便將@Transactional轉換為任何方法上的運行時行為。
要使用aspectj,請編寫
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
代替
<tx:annotation-driven transaction-manager="transactionManager" />
資源:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html
我解決了我的問題。 謝謝大家指出允許AspectJ
但這還沒有結束。 我進行了更深入的研究,結果發現@Transactional
Spring
Beans
有一個方面proxy
,它負責(就獲取而言)對@Transactional
方法的事務(創建,回滾等)進行操作。 但是它無法自引用,因為它繞過了proxy
,因此不會創建新的事務。 我用來完成此工作的一種簡單方法是調用函數pay(..)
而不是引用此函數,而是調用spring容器中的bean,如下所示:
UsersDaoImpl self = (UsersDaoImpl)this.context.getBean("usersDao");
self.pay(from, 10);
現在,由於它引用了Bean,因此它通過了proxy
因此創建了一個新事務。
僅出於學習問題,我使用這兩行來檢測兩個事務是否是相同的對象:
TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
System.out.println("Current transaction: " + status.toString());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.