簡體   English   中英

Spring Hibernate事務傳播無法正常工作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM