1. 程式人生 > >spring框架多個數據庫操作需統一提交事務回滾機制解析以及解決辦法

spring框架多個數據庫操作需統一提交事務回滾機制解析以及解決辦法

1、遇到的問題

  當我們一個方法裡面有多個數據庫儲存操作的時候,中間的資料庫操作發生的錯誤。虛擬碼如下:

複製程式碼
public method() {
    Dao1.save(Person1);
    Dao1.save(Person2);

    Dao1.save(Person2);//假如這句發生了錯誤,前面的兩個物件會被儲存到資料庫中
    Dao1.save(Person2);
}
複製程式碼

  期待的情況:發生錯誤之前的所有資料庫儲存操作都回滾,即不儲存

  正常情況:前面的資料庫操作會被執行,而發生資料庫操作錯誤開始及之後的所有的資料儲存操作都將失敗。這樣子應該都不是我們要的結果吧。

  當遇到這種情況,我們就可以使用Spring的事務解決這個問題。

2、異常的一些基本知識

1) 異常的架構

  異常的繼承結構:Throwable為基類,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception。Error和RuntimeException及其子類成為未檢查異常(unchecked),其它異常成為已檢查異常(checked)。 

2)Error異常

  Error表示程式在執行期間出現了十分嚴重、不可恢復的錯誤,在這種情況下應用程式只能中止執行,例如JAVA 虛擬機器出現錯誤。Error是一種unchecked Exception,編譯器不會檢查Error是否被處理,在程式中不用捕獲Error型別的異常。一般情況下,在程式中也不應該丟擲Error型別的異常。

3)RuntimeException異常

  Exception異常包括RuntimeException異常和其他非RuntimeException的異常。
  RuntimeException 是一種Unchecked Exception,即表示編譯器不會檢查程式是否對RuntimeException作了處理,在程式中不必捕獲RuntimException型別的異常,也不必在方法體宣告丟擲 RuntimeException類。RuntimeException發生的時候,表示程式中出現了程式設計錯誤,所以應該找出錯誤修改程式,而不是去捕獲RuntimeException。

4)Checked Exception異常

  Checked Exception異常,這也是在程式設計中使用最多的Exception,所有繼承自Exception並且不是RuntimeException的異常都是checked Exception,上圖中的IOException和ClassNotFoundException。JAVA 語言規定必須對checked Exception作處理,編譯器會對此作檢查,要麼在方法體中宣告丟擲checked Exception,要麼使用catch語句捕獲checked Exception進行處理,不然不能通過編譯。

3、例項

  這裡使用的事務配置如下:

複製程式碼
 <!-- Jpa 事務配置 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <!-- 開啟註解事務 -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
複製程式碼

  在spring的配置檔案中,如果資料來源的defaultAutoCommit設定為True了,那麼方法中如果自己捕獲了異常事務不會回滾的,如果沒有自己捕獲異常則事務會回滾,如下例
比如配置檔案裡有這麼條記錄

複製程式碼
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> 

<property name="xxx" value="xxx"/> 

<property name="xxx" value="xxx"/>

 ....
 <property name="defaultAutoCommit" value="true" /> 

</bean>
複製程式碼

  可能你會發現你並沒有配置這個引數,是不是他就不會自動提交呢?答案是不是的,我這裡是使用了com.alibaba.druid.pool.DruidDataSource作為資料庫連線池,預設的defaultAutoCommit就是true,可以看下面的原始碼

  那麼現在有兩個情況
  情況1:如果沒有在程式中手動捕獲異常

@Transactional(rollbackOn = { Exception.class })  
public void test() throws Exception {  
     doDbStuff1();  
     doDbStuff2();//假如這個操作資料庫的方法會丟擲異常,現在方法doDbStuff1()對資料庫的操作   會回滾。  
}  

  情況2:如果在程式中自己捕獲了異常

複製程式碼
@Transactional(rollbackOn = { Exception.class })  
public void test() {  
     try {  
        doDbStuff1();  
        doDbStuff2();//假如這個操作資料庫的方法會丟擲異常,現在方法doDbStuff1()對資料庫的操作  不會回滾。  
     } catch (Exception e) {  
           e.printStackTrace();     
     }  
}  
複製程式碼

  現在如果我們需要手動捕獲異常,並且也希望拋異常的時候能回滾腫麼辦呢?
  下面這樣寫就好了,手動回滾事務:

複製程式碼
@Transactional(rollbackOn = { Exception.class })  
public void test() {  
     try {  
        doDbStuff1();  
        doDbStuff2();  
     } catch (Exception e) {  
          e.printStackTrace();     
          TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是這一句了,加上之後,如果doDbStuff2()拋了異常,                                                                                       //doDbStuff1()是會回滾的  
     }  
}  
複製程式碼

   致謝:感謝您的閱讀!轉文請加原文連結,謝謝!

相關推薦

spring框架個數操作統一提交事務機制解析以及解決辦法

1、遇到的問題   當我們一個方法裡面有多個數據庫儲存操作的時候,中間的資料庫操作發生的錯誤。虛擬碼如下: public method() { Dao1.save(Person1); Dao1.save(Person2); Dao1.sa

JAVA資料庫操作二(個數操作+Spring data + jpa)

本文我們將主要實現同時操作兩個資料庫,(oracle 和mysql) 當然為了展示技巧,本文將以java配置為主 首先是daoContext.xml的內容 <?xml version="1.0" encoding="UTF-8"?> <beans xml

Laravel框架實現同時連線個數

laravel4.2版本, 1.修改配置檔案:config/database.php 'pgsql' => array( 'driver' => 'pgsql', 'host' => '10.0.2.203', 'database'

dotnetcore ef 呼叫個數時使用者命令執行操作報錯

dotnetcore ef 呼叫多個數據庫時使用者命令執行操作報錯 1、多個DbContext 時報錯: 報錯: More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for

用 Binds 操作個數

用 Binds 操作多個數據庫 從 0.12 開始, Flask-SQLAlchemy 可以容易地連線到多個數據庫。為了實現 這個功能,預配置了 SQLAlchemy 來支援多個“binds”。 什麼是 binds ?在 SQLAlchemy 中,一個 bind 是可以執行 SQ

Redis實現key過期監聽,並操作redis的個數,整合到SpringBoot

最近來了個新的需求,需要使用定時器完成,本想以為用個@Scheduled()就輕易搞定的,詳細瞭解後,事情卻並沒有這麼簡單......。所以接到需求後,需要找產品明確明確再次明確,才開工,不然的話你本以為做好的工作卻是一場空。 業務場景邏輯解析:第一個請求進來,需要把請求引

Spring+jpa連線個數

1.persistence.xml<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="

單個工程中Spring+Mybatis連線個數的配置(個人分享版本)

上一篇部落格說到同一個問題,經過和朋友的研究已經參考網上的資料,現在給出一份更簡潔的配置。 情景:現在單個工程中需要連線兩個庫,這兩個庫在同一個mysql中,兩個庫都需要進行讀寫。 解決: 第一步:將spring和mybatis整合,這個過程就不具體演示了,在這個過程中建立

一個專案中hibernate框架下配置個數

hibernate框架下配置多個數據庫 當我們在同一個專案中需要同時連線多個數據庫時,在hibernate框架下的我們可以通過配置多個sessionFactory與多個連線池配置實現獲取不同資料庫的連線session物件。 初始化hibernate的se

ThinkPHP 3.2 連線個數使用(M、D)操作說明

<?php /** * 配置檔案 */ return array( // 預設連線資料庫 'DB_TYPE' => 'mysql', // 資料庫型別 'DB_H

OsharpNS輕量級.net core快速開發框架簡明入門教程-上下文配置(個數的使用)

asi nag eve ble pro rpo 通過 現實 readonly OsharpNS輕量級.net core快速開發框架簡明入門教程 教程目錄 從零開始啟動Osharp 1.1. 使用OsharpNS項目模板創建項目 1.2. 配置數據庫連接串並啟動項目 1.3

訪問Access數(有個數時 體現態)

.sh into img 保留 tag int32 無效 要求 oledb 如果想編寫單機版MIS、小型網站等對數據庫性能要求不高的系統,又不想安裝SQLServer,可以使用Access(MDAC),只要一個mdb文件就可以了。使用Access創建mdb文件,建表。Ole

django 對個數支持

django 多數據庫 數據庫自動路由使用多數據庫最簡單的方法是建立一個數據庫路由模式。默認的路由模式確保對象’粘滯‘在它們原始的數據庫上(例如,從foo 數據庫中獲取的對象將保存在同一個數據庫中)。默認的路由模式還確保如果沒有指明數據庫,所有的查詢都回歸到default數據庫中。你不需要做任何事情來

Django框架——模型(數操作)

models py -- models.py-- ORM(object-relation mapping) 實現數據模型與數據庫的解耦;# 對象,關系,映射;1.根 據對象的類型生成表結構;2.將對象、列表的操作,轉換為sql語句;3.將sql查詢到的結果轉換為對象、列表;-- 字段類型# 所有字段類

Hibernate 連接訪問個數(含訪問不同數的相同表)(轉)

手指 row 測試 ransient cat 接口 ava 針對 pos 利用hibernate訪問不同數據庫中的不同表或不同數據庫中的相同表。 本人在開發過程中的解決方案,希望大家交流。一般用myEclipse工具會自動生成Hibernate的相關文件,大致有下面幾類:

YII2 gii 配置個數, 或者個配置文件的時候 gii 出現數表不存在, 實現選擇數 Table '****' does not exist. 解決 就在gii 頁面 選擇數選項

TP 實現 分享 inf 技術 bsp 多個 ble png 用著用著就暈了 就在gii 頁面 選擇數據庫選項 (配置多個數據庫後制動就該有選項) YII2 gii 配置多個數據庫, 或者多個配置文件的時候 gii 出現數據表不存在, 實現選擇數據庫 Table

SpringBoot(三)通過properties實現個數環境自動切換配置

方式 info 本地 所有 -c int 安裝 style 過多 前面的文章已經介紹了CentOS部署SpringBoot項目從0到1的詳細過程,包括Linux安裝ftp、Tomcat以及Java jdk的全部過程。這篇文章主要介紹關於springboot如何通過多

StringRedisTemplate個數時RedisDao

最近開發專案中使用Redis資料庫,看了原來人寫的程式碼,覺得挺差的。由於應用訪問Redis中的不同資料庫,原來ReidsDao層竟然使用MapDao,StringDao,HashDao,然後在這些Dao都注入不同資料庫的StringRedisTemplateBean了。雙休時充充電,把那一部分

SpringBoot2.0.4配置個數

使用場景: 一個Spring Boot服務根據不同的業務邏輯需要對不同的資料庫進行操作。 一、舉例說明 假設需要處理的兩個資料庫是test1、test2,那麼必須要有的是: 兩個資料庫的配置引數(寫在配置檔案application.properties)。 兩個

Laravel配置控制器內切換個數(或任意切換資料庫)

1. 知識點:     Laravel預設資料庫是取.env和datebase.php中mysql填寫的資料庫。     如果需要切換多個數據庫,就需要填寫新的資料庫配置。     新的資料庫不需要.env檔案依賴。 &