欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring系列之事物管理

 更新時間:2021年09月02日 14:20:54   作者:程序員阿牛  
這篇文章主要介紹了Spring系列之事物管理,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring方面知識具有一定的參考學(xué)習(xí)價值,需要的朋友們一起學(xué)習(xí)學(xué)習(xí)吧

前言

我們都知道Spring給我們提供了很多抽象,比如我們在操作數(shù)據(jù)庫的過程中,它為我們提供了事物方面的抽象,讓我們可以非常方便的以事物方式操作數(shù)據(jù)庫。不管你用JDBC、Mybatis、Hibernate等任何一種方式操作數(shù)據(jù)庫,也不管你使用DataSource還是JTA的事物,Spring事物抽象管理都能很好的把他統(tǒng)一在一起。接下來看一下事物的抽象核心接口

Spring事務(wù)抽象

PlatformTransactionManager是事物管理器接口

//事務(wù)管理器接口有以下幾個接口,獲取事物信息,提交和回滾
public interface PlatformTransactionManager {
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

常見的事物管理器有以下幾種

  • DataSourceTransactionManager
  • HibernateTransactionManager
  • JtaTransactionManager

這些管理器都實(shí)現(xiàn)了PlatformTransactionManager中的三個接口,實(shí)現(xiàn)邏輯略有差別,但是對用戶來講區(qū)別不大

定義事物的一些參數(shù):
一些事物的參數(shù)在TransactionDefinition.java中,詳情如下:

public interface TransactionDefinition {
	  int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
		//默認(rèn)隔離級別,和數(shù)據(jù)庫的隔離級別一致
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
		//默認(rèn)不超時
    int TIMEOUT_DEFAULT = -1;
}

下面兩張圖對這些參數(shù)進(jìn)行了說明:
7種事務(wù)傳播特性:


四種事務(wù)隔離級別:
在看事務(wù)隔離級別前需要先了解下什么是臟讀、不可重復(fù)讀、幻讀
臟讀: 臟讀就是一個事物未提交的數(shù)據(jù),被另外一個事物讀到了,顯然這種情況不可接受
不可重復(fù)讀: 不可重復(fù)讀是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù),前后讀取的結(jié)果不一致。
幻讀: 事務(wù)A對表中的一個數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時事務(wù)B也修改了這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么就會發(fā)生操作事務(wù)A的用戶發(fā)現(xiàn)表中還存在沒有修改的數(shù)據(jù)行,就好像發(fā)生了幻覺一樣
知道了以上幾個概念,我們來看看隔離級別:

這里我們可以看到,Spring并不是提供了所有的事物管理的實(shí)現(xiàn),而是提供了標(biāo)準(zhǔn)的事物管理器的操作接口PlatformTransactionManager, 并且規(guī)范了其行為,具體的事物實(shí)現(xiàn)由各個平臺自行實(shí)現(xiàn)。這就是Spring的事物抽象。

Spring之編程式事物

Spring提供了TransactionTemplate工具類可以很方便的使用編程式事務(wù)。默認(rèn)情況下TransactionTemplate使用的是DataSourceTransactionManager。
在Spring上下文中,我們不配置TransactionTemplate這個bean,也能獲取到TransactionTemplate。比如下面的例子。

@Service
public class UserInfoService {

    @Resource
    private UserInfoDAO userInfoDAO;
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    public void updateUser1(){
        transactionTemplate.execute(transactionStatus -> {
            userInfoDAO.updateUserName(1,"zhangsanfeng");
            transactionTemplate.execute(transactionStatus2 -> {
                userInfoDAO.updateUserName(2,"lisi");
                return null;
            });
            return null;
        });
    }
}

由于Spring默認(rèn)的事物傳播特性是PROPAGATION_REQUIRED,我們來做一下驗(yàn)證,看是不是這樣


上面兩幅圖可以看出,TransactionStatus中的newTransaction屬性,第一個是true,第二個是false,正好符合PROPAGATION_REQUIRED所描述的情況。其他的傳播特性可以自己去驗(yàn)證。

聲明式事物

除了編程式事物外,Spring還為我們提供了聲明式事物。使用@Transactional注解。
@Transactional 可以作用于接口、接口方法、類以及類方法上。當(dāng)作用于類上時,該類的所有 public 方法將都具有該類型的事務(wù)屬性,同時,我們也可以在方法級別使用該注解來覆蓋類級別的定義。

雖然 @Transactional 注解可以作用于接口、接口方法、類以及類方法上,但是 Spring 建議不要在接口或者接口方法上使用該注解,因?yàn)檫@只有在使用基于接口的代理時它才會生效。另外, @Transactional 注解應(yīng)該只被應(yīng)用到 public 方法上,這是由 Spring AOP 的本質(zhì)決定的。如果你在 protected、private 或者默認(rèn)可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。

@Transactional的rollbackFor屬性可以設(shè)置一個 Throwable 的數(shù)組,用來表明如果方法拋出這些異常,則進(jìn)行事務(wù)回滾。默認(rèn)情況下如果不配置rollbackFor屬性,那么事務(wù)只會在遇到RuntimeException的時候才會回滾。
下面的代碼事物就不會生效:

 @Transactional
    public void updateUser2() throws Exception {
        int r1 = userInfoDAO.updateUserName(1,"wanger");
        int r2 = userInfoDAO.updateUserName(2,"mawu");
        if (r2==1){
            throw new Exception();
        }
    }

如果我們把拋出的異常改成RuntimeException,這時候事物就會生效了?;蛘咧付ó惓W屖挛锷В热?@Transactional(rollbackFor = Exception.class),這樣碰到所有的異常事物都會生效了。

為什么加了@Transactional注解事物就生效了?

這是因?yàn)镾pring容器會為加了這個注解的對象生成一個代理對象,實(shí)際調(diào)用的時候,實(shí)際上是調(diào)用的代理對象。 代理對象的實(shí)現(xiàn)了AOP的增強(qiáng),實(shí)現(xiàn)了事物的實(shí)現(xiàn)。

通過注解怎么實(shí)現(xiàn)指定的傳播特性和隔離級別的?

public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    String[] label() default {};

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    String timeoutString() default "";

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

代碼中可以看出,我們可以指定隔離級別和傳播特性,在Spring為我們生成代理類的時候,會讀取這些屬性,體現(xiàn)在增強(qiáng)邏輯中。

事物失效的8種情況及解決辦法

數(shù)據(jù)庫引擎不支持事務(wù)

這里以 MySQL 為例,其 MyISAM 引擎是不支持事務(wù)操作的,InnoDB 才是支持事務(wù)的引擎,一般要支持事務(wù)都會使用 InnoDB,這時候選擇支持事物的數(shù)據(jù)庫即可(好像是廢話,哈哈哈)

沒有被 Spring 管理

這個好像沒什么可說的,脫離了Spring的管理,還談什么Spring事物管理。

方法不是 public 的

@Transactional 只能用于 public 的方法上,否則事務(wù)不會失效,如果要用在非 public 方法上,可以開啟 AspectJ 代理模式。

數(shù)據(jù)源沒有配置事務(wù)管理器

相當(dāng)于沒開啟事務(wù)管理,如果不是Springboot情況需要進(jìn)行如下操作。

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

如果是SpringBoot,在啟動類上直接加上注解@EnableTransactionManagement即可。

傳播特性配錯了

傳播特性配置成,Propagation.NOT_SUPPORTED或者Propagation.NOT_SUPPORTED,改成支持事物的傳播特性即可。

異常類型錯誤

因?yàn)槟J(rèn)的異常類型是運(yùn)行時異常,如果拋出了其他異常就不生效。
解決方式:
1、將異常改成運(yùn)行時異常
2、指定異常進(jìn)行事物回滾,如:@Transactional(rollbackFor = Exception.class)

異常被吃掉了

如果你代碼這么寫,事物不生效:

  @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
        int r1 = userInfoDAO.updateUserName(1,"3");
        int r2 = userInfoDAO.updateUserName(2,"4");
        if (r2==1){
            throw new RuntimeException();
        }
        try {
            
        }catch (Exception e){
            
        }
    }

解決辦法: 必須要拋出異常,否則Spring事務(wù)管理,不會走到回滾邏輯

類內(nèi)部調(diào)用

@Service
public class UserInfoService {
    public void justUpdate(){
        updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {

    }
}

上述代碼不生效,因?yàn)閮?nèi)部調(diào)用不會涉及到代理類的調(diào)用,更不會有AOP的增強(qiáng),因此不會生效。
解決辦法:
1、自注入

@Service
public class UserInfoService {
   @Autowired
    private UserInfoService userInfoService;
    public void justUpdate(){
        userInfoService.updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {

    }
}

2、Spring上下文

@Service
public class UserInfoService {
    ApplicationContext applicationContext;
    public void justUpdate(){
		   UserInfoService userInfoService = (UserInfoService) applicationContext.getBean("userInfoService");
        userInfoService.updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
    }
}

3、獲取他的代理類,直接調(diào)用代理類

@Service
public class UserInfoService {
    public void justUpdate(){
		   ((UserInfoService) AopContext.currentProxy()).updateUser2();
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateUser2() {
    }
}

----------------------------END---------------------------

以上就是Spring系列之事物管理的詳細(xì)內(nèi)容,更多關(guān)于Spring 事物管理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaSE實(shí)現(xiàn)電影院系統(tǒng)

    JavaSE實(shí)現(xiàn)電影院系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了JavaSE實(shí)現(xiàn)電影院系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Springboot使用@Valid 和AOP做參數(shù)校驗(yàn)及日志輸出問題

    Springboot使用@Valid 和AOP做參數(shù)校驗(yàn)及日志輸出問題

    這篇文章主要介紹的Springboot使用@Valid 和AOP做參數(shù)校驗(yàn)及日志輸出問題,本文通過代碼講解的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • springMVC引入Validation的具體步驟詳解

    springMVC引入Validation的具體步驟詳解

    本文簡單介紹如何引入validation的步驟,如何通過自定義validation減少代碼量,提高生產(chǎn)力,非常具有實(shí)用價值,需要的朋友可以參考下
    2018-05-05
  • java中jvm逃逸問題分析

    java中jvm逃逸問題分析

    本篇文章給大家詳細(xì)總結(jié)了java中jvm逃逸問題的相關(guān)內(nèi)容,有興趣的朋友可以根據(jù)小編一起學(xué)習(xí)下。
    2018-02-02
  • SpringSecurity?表單登錄的實(shí)現(xiàn)

    SpringSecurity?表單登錄的實(shí)現(xiàn)

    本文主要介紹了SpringSecurity?表單登錄的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Maven 搭建SpringMVC+Hibernate項(xiàng)目詳解

    Maven 搭建SpringMVC+Hibernate項(xiàng)目詳解

    本文主要介紹Maven 搭建SpringMVC+Hibernate的知識,這里整理了詳細(xì)的資料,并附示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • java實(shí)現(xiàn)攝像頭截圖功能

    java實(shí)現(xiàn)攝像頭截圖功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)攝像頭截圖功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • 在Spring Boot框架中使用AOP的正確姿勢

    在Spring Boot框架中使用AOP的正確姿勢

    aop是spring的兩大功能模塊之一,功能非常強(qiáng)大,為解耦提供了非常優(yōu)秀的解決方案。下面這篇文章主要給大家介紹了如何在Spring Boot框架中使用AOP的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • mybatis中延遲加載Lazy策略的方法

    mybatis中延遲加載Lazy策略的方法

    這篇文章主要介紹了mybatis中延遲加載Lazy策略,需要的朋友可以參考下
    2018-06-06
  • nohup運(yùn)行Java tail查看日志方式

    nohup運(yùn)行Java tail查看日志方式

    nohup命令允許程序在用戶退出賬戶或關(guān)閉終端后繼續(xù)運(yùn)行,常與"&"結(jié)合使用以實(shí)現(xiàn)程序的后臺執(zhí)行,配合重定向操作,nohup可以將程序輸出保存到日志文件中,如nohup java -jar XXX.jar &> myout.log &,此外,tail命令可用于實(shí)時監(jiān)控日志文件的變化
    2024-09-09

最新評論