使用Spring事物時不生效的場景及解決方法
一.類沒被Spring管理
如果我們的類沒有被Spring管理,那么即使使用了Spring事物也不會生效,要讓Spring管理我們的類,需要標注@Component,@Service等注解。

二.沒有標注@Transactional注解的方法調用了標注@Transactional注解的方法
如果一個方法沒有使用@Transactional注解,但是它去調用了帶@Transactional注解的方法,那么當前方法的事物不生效。
public void saveUser(User user) throws Exception {
save(user);
}
@Transactional(rollbackFor = Exception.class)
public void save(User user) {
try {
userDao.save(user);
exceptionMethod();
roleService.save(user.getRole());
} catch (Exception e) {
throw new RuntimeException(e);
}
}如上所示,saveUser方法調用了save方法,但是saveUser沒有標@Transactional注解,而它調用了save方法,save方法標了@Transactional,不過事物不會生效,這是因為方法沒被代理,直接是普通方法調用,所以事物自然不生效。
如果一個方法中調用了其他方法,需要在主方法上加@Transactional注解這個方法才能被代理,如下代碼,當然,遠程調用@Transactional就不生效了,就需要分布式事物了。
@Transactional(rollbackFor = Exception.class)
public void saveAnnotation(User user) throws Exception {
save(user);
}
public void save(User user) {
try {
userDao.save(user);
exceptionMethod();
roleService.save(user.getRole());
} catch (Exception e) {
throw new RuntimeException(e);
}
}三.異常使用不正確
如果異常使用不當,那么事物也不會生效,這里的異常有兩種,一種是我們拋出的異常,一種是@Transactional注解所接受的異常。
1.如果我們在程序代碼中自己捕獲了異常導致Spring事物捕獲不到異常,那么事物也不會生效,如下,exceptionMethod方法捕獲了異常并打印異常信息,那么異常并不會被Spring事物捕獲到,所以事物并不會回滾。
@Transactional(rollbackFor = Exception.class)
public void saveAnnotation(User user) throws Exception {
userDao.save(user);
exceptionMethod();
roleService.save(user.getRole());
}
private void exceptionMethod() throws Exception {
try {
int i = 1 / 0;
} catch (Exception e) {
e.printStackTrace();
}
}如果需要事物回滾,那么就需要將異常拋到saveAnnotation方法,這樣Spring事物才能感知到異常,從而進行事物回滾。
2.@Transactional注解有一個屬性rollbackFor,它代表回滾的異常,也就是說只有捕獲到這種異常事物才會回滾,它默認的是RunTimeException。
@Transactional
public void saveAnnotation(User user) throws Exception {
userDao.save(user);
exceptionMethod();
roleService.save(user.getRole());
}
private void exceptionMethod() throws Exception {
try {
int i = 1 / 0;
} catch (Exception e) {
throw new Exception("拋出異常");
}
}如上代碼,exceptionMethod方法拋出了Exception異常,而@Transactional注解我們沒有指定rollbackFor,所以使用的是默認的RunTimeException,所以事物不能回滾,如果我們需要事物回滾,需要讓rollbackFor指定的異常是拋出異常的父類或者和自己一樣才行,如下所示。
@Transactional(rollbackFor = Exception.class)
public void saveAnnotation(User user) {
userDao.save(user);
exceptionMethod();
roleService.save(user.getRole());
}
private void exceptionMethod() {
try {
int i = 1 / 0;
} catch (Exception e) {
throw new ArithmeticException("運算異常");
}
}四.不正確的傳播行為
如果傳播行為使用的是NOT_SUPPORTED,那么事物無法回滾。NOT_SUPPORTED表示當前方法不應該有事務,如果有事務存在,將它掛起,以無事務狀態(tài)運行。
@Transactional(propagation = Propagation.NOT_SUPPORTED)
五.方法修飾為private
如果方法以private修飾,那么方法將不會被代理,事物自然不會生效,不過如果在進行業(yè)務開發(fā)的時候,對于需要其它類進行調用的方法,我們都是以public修飾,因為如果以private修飾,其它類想要訪問的話需要借助反射才能訪問,在IDEA中,@Transactional方法如果修飾為private,會有錯誤提醒,但是運行不會報錯。

不過一些場景我們可能需要反射調用,所以不應該避開這個問題,還是將其修飾為public。
六.數據庫不支持事物
如果數據庫不支持事物,那么即使項目中使用了Spring事物,也不會生效,因為Spring的事物最終也是JDBC的事物,JDBC事物也要數據庫支持事物才行,MySQL中MyISAM存儲引擎不支持事物,InnoDB才支持事物。
七.沒有配置事務管理器,導致事務失效
使用非SpringBoot項目,需要配置PlatformTransactionManager,需要加上@EnableTransactionManagement注解,如果是SpringBoot項目,那么可以不用配置,因為SpringBoot默認幫我們裝配好了,我們直接使用就好。
以上就是使用Spring事物時不生效的場景及解決方法的詳細內容,更多關于使用Spring事物時不生效的資料請關注腳本之家其它相關文章!
相關文章
Spring超出最大會話數(Max?sessions?limit?reached:?10000)
在Spring系統(tǒng)中遇到的Maxsessionslimitreached:10000錯誤,該錯誤由于會話數超過默認限制10000而觸發(fā),下面就來介紹一下解決方法,感興趣的可以了解一下2024-12-12
Intelli IDEA安裝Scala插件并安裝Scala軟件和配置環(huán)境變量的詳細教程
這篇文章主要介紹了Intelli IDEA安裝Scala插件并安裝Scala軟件和配置環(huán)境變量的詳細教程,需要的朋友可以參考下2020-10-10
SpringCloud可視化鏈路追蹤系統(tǒng)Zipkin部署過程
這篇文章主要介紹了SpringCloud可視化鏈路追蹤系統(tǒng)Zipkin部署過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03
詳解Java中的checked異常和unchecked異常區(qū)別
這篇文章主要介紹了詳解Java中的checked異常和unchecked異常區(qū)別,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

