Spring(四):事務管理

事務

首先,我們要知道事務是什麼

構成單一邏輯工作單元的操作集合稱爲事務

事務的ACID特性

  • 原子性:不可分割的最小操作單位,要麼同時成功,要麼同時失敗
  • 一致性:事務操作前後,數據總量不變
  • 隔離性:多個事務之間相互獨立
  • 持久性:當事務提交或回滾後,數據會持久化的保存數據

傳統編程的事務管理

在傳統的JAVA數據庫編程中,我們遵循的是打開連接-執行操作-提交事務-關閉連接,如下面的代碼:

Connection con = getCon();
con.setAutoCommit(false);
con.prepareStatement("UPDATE...").execute();
con.prepareStatement("UPDATE...").execute();
con.commit();
//conn.rollback();
con.close();

這樣就產生了很多模板代碼,而且依靠程序員手動提交事務,也十分不可靠

Spring對事務的管理

Spring的事務管理分爲兩類

  • 聲明式事務
  • 編程式事務

Spring定義了一個接口PlatformTransactionManager,我們只需要使用其實現類,將數據源交其管理,即可實現Spring事務管理

@Configuration
@EnableTransactionManagement // 開啓事務管理
@ComponentScan("wang.ismy.spring")
public class Config {

    @Bean
    public DataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql:///test");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123");
        return druidDataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }

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

這樣,當你在你的service中拋出異常的時候,Spring就會自動幫你進行事務回滾

    @Transactional(rollbackFor = Exception.class) // Spring默認只對運行期異常回滾,加上該屬性,則設置回滾的異常類型爲Exception
    public void transfer() {

        jdbcTemplate.execute("UPDATE account SET amount = 90 WHERE name = 'alice'");
        int a=1/0;
        jdbcTemplate.execute("UPDATE account SET amount = 110 WHERE name = 'bob'");

    }

屬性

@Transactional註解的一些屬性說明如下

  • read-only:是否是隻讀事務。默認false,不只讀。
  • isolation:指定事務的隔離級別。默認值是使用數據庫的默認隔離級別。
  • propagation:指定事務的傳播行爲。
  • timeout:指定超時時間。默認值爲:-1。永不超時。
  • rollback-for:用於指定一個異常,當執行產生該異常時,事務回滾。產生其他異常,事務不回滾。沒有默認值,任何異常都回滾。
  • no-rollback-for:用於指定一個異常,當產生該異常時,事務不回滾,產生其他異常時,事務回滾。沒有默認值,任何異常都回滾。

理解事務的傳播行爲

  • PROPAGATION_REQUIRED

簡單來說就是兩個被事務管理的方法都將在同一個事務內執行

  • PROPAGATION_REQUIRES_NEW

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Js4iUWgF-1575086151289)(https://docs.spring.io/spring/docs/5.2.1.RELEASE/spring-framework-reference/images/tx_prop_requires_new.png)]

而這個傳播行爲則是開啓一個新事務

  • PROPAGATION_NESTED

該傳播行爲則是與JDBC的保存點一樣,它使用了物理事務的保存點的概念

編程式事務

一般來說,編程式事務很少用,它就是把一些對數據庫的更新操作放在一起,來達到事務管理的目的

首先,我們需要一個

    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager manager){
        return new TransactionTemplate(manager);
    }

在使用的時候注入這個Template進行操作

    public void transfer(){
        transactionTemplate.execute((TransactionCallback<Void>) status -> {
            String sql = "UPDATE account SET money = money -200 WHERE uid = 41";
            String sql1 = "UPDATE account SET money = money +200 WHERE uid = 45";
            jdbcTemplate.update(sql);
            jdbcTemplate.update(sql1);
            return null;
        });
    }

這樣,也能進行事務管理

原理

最後,來探討一下Spring事務管理的原理

一句話,事務管理是通過AOP實現的,這個我們通過獲取Bean的實際類型就知道

System.out.println(context.getBean(AccountService.class).getClass());
// 結果:class wang.ismy.spring.AccountService$$EnhancerBySpringCGLIB$$f8bd6705

這是Spring官網給出的一個受事務管理的概念視圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-IcLIP2fR-1575086151289)(https://docs.spring.io/spring/docs/5.2.1.RELEASE/spring-framework-reference/images/tx.png)]

AOP增強了我們的Service類,當真實的方法被調用前與調用後,Spring替我們完成commit/rollback等操作,以實現事務管理

發佈了36 篇原創文章 · 獲贊 0 · 訪問量 8804
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章