朝花夕拾之Spring 使用AOP進行事務管理

到底什么是事務管理?
場景:
下訂單,需要對數據的操作有

  1. 檢查庫存
  2. 扣除庫存
  3. 生成訂單記錄
    三次數據操作的集合就是一個事務。

對于這樣的事務,報錯情況有

  1. 庫存不滿足 拋出 NotEnoughException
  2. 扣除庫存時失敗 拋出 RemoveInventoryException
  3. 生成訂單時失敗 拋出 CreateOrderException
    如果第一步和第二步出錯還好,可以直接在業務邏輯里處理Exception就好,但是如果在第三步的時候除了錯,就需要把第二步扣除掉的庫存恢復。這是最原始的邏輯。

數據庫提供了事務操作的語句

begin
commit
rollback

對應Java 封裝操作

Connection cnn=null;
conn=DriverManager.getConnection(url,user,password);
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
//這里執行語句

//如果成功的話
conn.commit();
//如果失敗的話
conn.rollback();

如果你愿意,可以把所有的業務邏輯這么封裝。但是如果借助AOP+Spring的話,一切都變得異常簡單了!

從配置開始

Maven中添加tx依賴庫(其余Spring系列、Mybatis 等參照前文配置)

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

依然是Java Config,只需要兩步,第一步配置DataSourceTransactionManagerBean。第二步聲明使用注解事務@EnableTransactionManagement
因為我將DataSource配置在了 MyBatisConfig.java內,所以和數據庫關聯的一起配置在內了(亦可新建.java,注解@Configuration,在WebMVCIniatializer.java 內的getRootConfigClasses()里添加這個配置類)
完整類如下。

@Configuration
@MapperScan("jufou.info.mapper")
@EnableTransactionManagement
public class MyBatisConfig {
    @Bean
    public DataSource dataSource(){
        BasicDataSource basicDataSource=new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUsername("root");
        basicDataSource.setPassword("Nieve7658");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        return basicDataSource;
    }
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(){
        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/jufou/info/mybatis/mappers.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSessionFactoryBean;
    }
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(){
        return new DataSourceTransactionManager(dataSource());
    }
    @Bean
    public SqlSession sqlSession(){
        SqlSessionTemplate sqlSessionTemplate= null;
        try {
            sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean().getObject());
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            return sqlSessionTemplate;
        }
    }
}

使用注解事務管理

在你需要事務管理函數上使用@Transactional即可。如果在類上注解,則該類所有函數都會有事務管理

事務管理的具體配置

事務管理配置分為

傳播行為

REQUIRED:業務方法需要在一個容器里運行。如果方法運行時,已經處在一個事務中,那么加入到這個事務,否則自己新建一個新的事務。

NOT_SUPPORTED:聲明方法不需要事務。如果方法沒有關聯到一個事務,容器不會為他開啟事務,如果方法在一個事務中被調用,該事務會被掛起,調用結束后,原先的事務會恢復執行。

REQUIRESNEW:不管是否存在事務,該方法總匯為自己發起一個新的事務。如果方法已經運行在一個事務中,則原有事務掛起,新的事務被創建。

MANDATORY:該方法只能在一個已經存在的事務中執行,業務方法不能發起自己的事務。如果在沒有事務的環境下被調用,容器拋出例外。

SUPPORTS:該方法在某個事務范圍內被調用,則方法成為該事務的一部分。如果方法在該事務范圍外被調用,該方法就在沒有事務的環境下執行。

NEVER:該方法絕對不能在事務范圍內執行。如果在就拋例外。只有該方法沒有關聯到任何事務,才正常執行。

NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。

隔離級別(來自百度百科)

未授權讀取也稱為讀未提交(Read Uncommitted):允許臟讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

授權讀取也稱為讀提交(Read Committed):允許不可重復讀取,但不允許臟讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

可重復讀取(Repeatable Read):禁止[不可重復讀取]和臟讀取,但是有時可能出現幻讀數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,不能并發執行。僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

設定對特定Exception生效

默認對所有Exception生效
使用rollbackFornotRollbackFor完成

Sample
@Transactional(isolation =  Isolation.READ_COMMITTED,rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • 很多人喜歡這篇文章,特此同步過來 由淺入深談論spring事務 前言 這篇其實也要歸納到《常識》系列中,但這重點又...
    碼農戲碼閱讀 4,760評論 2 59
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,330評論 11 349
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • MySQL技術內幕:InnoDB存儲引擎(第2版) 姜承堯 第1章 MySQL體系結構和存儲引擎 >> 在上述例子...
    沉默劍士閱讀 7,452評論 0 16
  • 文|貓石魚 時間是每一個人擁有的最為稀缺的資源。 不可否認,我們這個時代,發展異常迅猛,整個社會都在以奔跑的速度前...
    貓石魚閱讀 324評論 0 4