以Transaction注解為例:
@Service public class TestService { @Autowired Dao dao; @Transactional public void methodOne(Object o) { dao.save(o); } public void methodTwo(Object o) { methodOne(o); } }
檢查事務是否啟動:
設置log leve為debug,可以查看是否有下面這個log,判斷是否啟動了Transaction:
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name...
原因:
Spring在掃描bean的時候會掃描方法上是否包含@Transactional注解,如果包含,Spring會為這個bean動態地生成一個子類(即代理類,proxy),代理類是繼承原來那個bean的。此時,當這個有注解的方法被調用的時候,實際上是由代理類來調用的,代理類在調用方法之前就會啟動Transaction。然而,如果這個有注解的方法是被同一個類中的其他方法調用的,那么該方法的調用並沒有通過代理類,而是直接通過原來的那個bean,所以就不會啟動Transaction,我們看到的現象就是@Transactional注解無效。
示例:
@Service class TestService{ @Transactional void methodOne(){ ... } void methodTwo(){ methodOne(); } } //Spring掃描注解后,創建了另外一個代理類,並為有注解的方法插入一個startTransaction()方法: class proxy$TestService{ TestService testService = new TestService(); void methodOne(){ startTransaction(); testService.methodOne(); } void methodTwo(){ //由於methodTwo()沒有注解,所以不會啟動transaction,而是直接調用TestService的實例的methodTwo()方法 testService.methodTwo(); } }
解決方法:
1.把這兩個方法分開到不同的類中。
2.把注解加到類名上面。