<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      spring事務管理

      1、spring事務管理基本介紹

      Spring 支持編程式事務管理以及聲明式事務管理兩種方式。

      編程式事務管理是侵入性事務管理,編程式事務每次實現都要單獨實現,但業務量大功能復雜時,使用編程式事務無疑是痛苦的,所以并不推薦使用。

      聲明式事務屬于無侵入式,不會影響業務邏輯的實現,只需要在配置文件中做相關的事務規則聲明或者通過注解的方式,便可以將事務規則應用到業務邏輯中。聲明式事務管理建立在AOP之上,其本質是對方法前后進行攔截,然后在目標方法開始之前創建或者加入一個事務,執行完目標方法之后根據執行的情況提交或者回滾。顯然聲明式事務管理要優于編程式事務管理,這正是Spring倡導的非侵入式的編程方式。

       

      Spring事務的本質其實就是數據庫對事務的支持,使用JDBC的事務管理機制就是利用 java.sql.Connection 對象完成對事務的提交。在沒有Spring幫我們管理事務之前,我們的做法:

      Connection conn = DriverManager.getConnection();
      try {  
          conn.setAutoCommit(false);  //將自動提交設置為false                         
          //執行CRUD操作
          ... 
          conn.commit();      //當兩個操作成功后手動提交  
      } catch (Exception e) {  
          conn.rollback();    //一旦其中一個操作出錯都將回滾,所有操作都不成功
          e.printStackTrace();  
      } finally {
          conn.colse();
      }

      事務是一系列的動作,一旦其中有一個動作出現錯誤,必須全部回滾,系統將事務中對數據庫的所有已完成的操作全部撤消,滾回到事務開始的狀態,避免出現由于數據不一致而導致的接下來一系列的錯誤。事務的出現是為了確保數據的完整性和一致性,在目前企業級應用開發中,事務管理是必不可少的。

       

      在企業級應用中,多用戶訪問數據庫是常見的場景,這就是所謂的事務的并發。事務并發所可能存在的問題:

      1. 臟讀:一個事務讀到另一個事務未提交的更新數據。
      2. 不可重復讀:一個事務兩次讀同一行數據,可是這兩次讀到的數據不一樣。
      3. 幻讀:一個事務執行兩次查詢,但第二次查詢比第一次查詢多出了一些數據行。
      4. 丟失更新:撤消一個事務時,把其它事務已提交的更新的數據覆蓋了。

       

      有了Spring,我們再也無需要去處理獲得連接、關閉連接、事務提交和回滾等這些操作,使得我們把更多的精力放在處理業務上。事實上Spring并不直接管理事務,而是提供了多種事務管理器。他們將事務管理的職責委托給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。

      具體的事務管理機制對 Spring 來說是透明的,它并不關心那些,那些是對應各個平臺需要關心的,所以 Spring 事務管理的一個優點就是為不同的事務API提供一致的編程模型,如JTA、JDBC、Hibernate、JPA。

      Spring并不直接管理事務,而是提供了多種事務管理器,他們將事務管理的職責委托給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。 Spring事務管理器的接口是 org.springframework.transaction.PlatformTransactionManager,通過這個接口,Spring為各個平臺如JDBC、Hibernate等都提供了對應的事務管理器,但是具體的實現由各個平臺自己實現。

       

      事務管理器接口 PlatformTransactionManager 通過 getTransaction(TransactionDefinition definition) 方法來得到事務,這個方法里面的參數是 TransactionDefinition 類,這個類就定義了一些基本的事務屬性。事務屬性包含了5個方面,如圖所示:

       

      2、聲明式事務管理之基于注解方式

      如果應用程序中直接使用JDBC來進行持久化,DataSourceTransactionManager會為你處理事務邊界。為了使用DataSourceTransactionManager,你需要使用如下的XML將其裝配到應用程序的上下文定義中:

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
      </bean>

      然后需要開啟事務注解,開啟事務注解需要引入命名空間 tx。完整的配置文件如下:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
      
          <!--開啟組件掃描-->
          <context:component-scan base-package="test, service, dao"></context:component-scan>
      
          <!--引入外部配置文件-->
          <context:property-placeholder location="classpath:jdbc.properties"/>
      
          <!--配置數據庫連接池-->
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${prop.driverClass}"></property>  <!--通過${}使用外部配置文件的值-->
              <property name="url" value="${prop.url}"></property>
              <property name="username" value="${prop.username}"></property>
              <property name="password" value="${prop.password}"></property>
          </bean>
      
          <!-- 配置JdbcTmplate -->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <!-- 注入dataSource -->
              <property name="dataSource" ref="dataSource"></property>
          </bean>
      
          <!-- 創建事務管理器-->
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean>
      
          <!-- 開啟事務注解-->
          <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
      </beans>

      然后在需要事務管理的地方加上 @Transactional 注解即可,在類上或者在方法上添加該注解都可以。如果注解是添加到類上,則表示給該類里的所有方法都添加事務;如果是添加到方法上,則表示給該方法添加事務。

       

      假設類有一個方法,A給B轉賬,需要給 A 的賬戶減少100元,同時需要給 B 增加100元,如果沒有使用事務,而執行過程中發生了異常,則可能導致數據發生不一致的問題:

      @Transactional
      @Service
      public class UserServiceImpl implements UserService {
          @Autowired
          private UserDao userDao;
          @Override
          public void updateUser(User user) {
              userDao.updateUser(user);
          }
      
          @Override
          public void transferAccount() {
             //減少100元
              userDao.reduceMoney();
      
              //模擬異常
              int i = 100 / 0;
      
              //增加100元
              userDao.addMoney();
          }
      }

      如果沒有添加 @Transactional 注解,則 A 減少了100元,但后面發生了異常,導致 B 并沒有增加100元,由此導致了數據不一致的問題。如果添加了注解,則發生異常會自動回滾,A賬戶的金額不會減少,B賬戶也不會增加。

       

      2.1、定義事務的傳播行為

      多事務方法(事務方法指的是將改變數據庫表數據的操作)之間互相調用時,對事務之間的管理就稱之為傳播行為(propagation behavior)。當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運行,也可能開啟一個新事務,并在自己的事務中運行。

      Spring 中定義了七種傳播行為:

      傳播行為 含義
      PROPAGATION_REQUIRED(默認值) 0 表示當前方法必須運行在事務中。如果當前事務存在,方法將會在該事務中運行。否則,會啟動一個新的事務,并在自己的事務內運行
      PROPAGATION_SUPPORTS 1 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那么該方法會在這個事務中運行
      PROPAGATION_MANDATORY 2 表示該方法必須在事務中運行,如果當前事務不存在,則會拋出一個異常
      PROPAGATION_REQUIRED_NEW 3 表示當前方法必須運行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager
      PROPAGATION_NOT_SUPPORTED 4 表示該方法不應該運行在事務中。如果存在當前事務,在該方法運行期間,當前事務將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager
      PROPAGATION_NEVER 5 表示當前方法不應該運行在事務上下文中。如果當前正有一個事務在運行,則會拋出異常
      PROPAGATION_NESTED 6

      表示如果當前已經存在一個事務,那么該方法將會在嵌套事務中運行。嵌套的事務可以獨立于當前事務進行單獨地提交或回滾。如果當前事務不存在,那么其行為與PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支持是有所差異的。可以參考資源管理器的文檔來確認它們是否支持嵌套事務

      定義傳播行為只需在 @Transactional 注解后面添加 propagation 參數即可:

      @Transactional(propagation = Propagation.REQUIRED)
      @Service
      public class UserServiceImpl implements UserService {
          
      }

       

      假設 A 方法調用了 B 方法,給 B 定義了 REQUIRED 傳播行為。如果 A 方法已經添加了事務,則 B 方法也在 A 的事務內運行;如果 A 方法沒有事務,則 B 方法會啟動一個新事務,并在該事務內運行。

       

      2.2、定義事務的隔離級別

      MySQL數據庫為我們提供了四種隔離級別:

      1.  Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
      2.  Read committed (讀已提交):只可避免臟讀的發生。
      3. Repeatable read (可重復讀,默認值):可避免臟讀、不可重復讀的發生。
      4. Serializable (串行化):臟讀、不可重復讀、幻讀均可避免

      事務的隔離級別可參考:http://www.rzrgm.cn/wenxuehai/p/13485440.html

       

      spring 設置事務的隔離級別只需要在 @Transactional 注解后面添加 isolation 參數即可,如下設置為 Read commited 級別:

      @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
      @Service
      public class UserServiceImpl implements UserService {
          
      }

       

      2.3、@Transactional 注解的其它參數

      2.3.1、超時時間(timeout)

      為了使應用程序很好地運行,事務不能運行太長的時間。因為事務可能涉及對后端數據庫的鎖定,所以長時間的事務會不必要的占用數據庫資源。事務超時就是事務的一個定時器,在特定時間內事務如果沒有執行完畢,那么就會自動回滾,而不是一直等待其結束。

      定義超時時間會規定事務必須在一定時間內進行提交,如果超時會自動進行回滾。

      spring 設置事務的超時時間只需要在 @Transactional 注解后面添加 timeout 參數即可。該值默認是 -1,即永不超時。我們可以手動設置超時時間,單位為秒:

      @Transactional(timeout = 10)
      @Service
      public class UserServiceImpl implements UserService {
          
      }

       

      2.3.2、是否只讀(readOnly)

      事務的其中一個特性是它是否為只讀事務,即只查詢。如果事務只對后端的數據庫進行該操作,數據庫可以利用事務的只讀特性來進行一些特定的優化。通過將事務設置為只讀,你就可以給數據庫一個機會,讓它應用它認為合適的優化措施。

      spring 設置事務是否只讀只需要在 @Transactional 注解后面添加 readOnly 參數即可,默認為 false,非只讀,即可讀可寫。我們可以手動設置為 true,即只讀:

      @Transactional(readOnly = true)
      @Service
      public class UserServiceImpl implements UserService {
          
      }

       

      2.3.3、回滾(rollbackFor)

      設置出現哪些異常時進行事務回滾。默認情況下,事務只有遇到運行期異常時才會回滾,而在遇到檢查型異常時不會回滾。但是我們可以設置事務在遇到特定的異常時進行回滾。同樣,你還可以聲明事務遇到特定的異常不回滾,即使這些異常是運行期異常。

      spring 設置事務對哪些異常進行回滾需要在 @Transactional 注解后面添加 rollbackFor 參數,并且該參數值為需要設置的異常的 class。

       

      2.3.4、不回滾(noRollbackFor)

      設置出現哪些異常不進行事務回滾。

      spring 設置事務對哪些異常進行回滾需要在 @Transactional 注解后面添加 noRollbackFor 參數,并且該參數值為需要設置的異常的 class。

       

      3、聲明式事務管理之基于xml配置方式

      通過 spring 的 xml 配置文件來實現事務管理:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
      
          <!--開啟組件掃描-->
          <context:component-scan base-package="test, service, dao"></context:component-scan>
      
          <!--引入外部配置文件-->
          <context:property-placeholder location="classpath:jdbc.properties"/>
      
          <!--配置數據庫連接池-->
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${prop.driverClass}"></property>  <!--通過${}使用外部配置文件的值-->
              <property name="url" value="${prop.url}"></property>
              <property name="username" value="${prop.username}"></property>
              <property name="password" value="${prop.password}"></property>
          </bean>
      
          <!-- 配置JdbcTmplate -->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <!-- 注入dataSource -->
              <property name="dataSource" ref="dataSource"></property>
          </bean>
      
          <!-- 創建事務管理器-->
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean>
      
          <!-- 配置通知 -->
          <tx:advice id="txAdvice" transaction-manager="transactionManager">
              <tx:attributes>
                  <!--指定需要添加事務的方法的規則-->
                  <tx:method name="*" propagation="REQUIRED" />
      <!--            <tx:method name="transferAccount" propagation="REQUIRED" />-->
              </tx:attributes>
          </tx:advice>
      
          <!-- 配置切入點和切面 -->
          <aop:config>
              <!-- 配置切入點 -->
              <aop:pointcut id="pt" expression="execution(* service.UserServiceImpl.*(..))" />
      
              <!-- 配置切面 -->
              <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
          </aop:config>
      
      </beans>

       

      posted @ 2021-04-30 16:57  wenxuehai  閱讀(187)  評論(0)    收藏  舉報
      //右下角添加目錄
      主站蜘蛛池模板: 国产91特黄特色A级毛片| 欧美人与动zozo在线播放| 国产精品无码专区| 久久亚洲国产欧洲精品一| 99国产精品自在自在久久| 望奎县| 亚洲一二三四区中文字幕| 亚洲国产片一区二区三区| 午夜精品久久久久久久久| 亚洲国产中文字幕精品| 97人妻精品一区二区三区| 国产成人精选视频在线观看不卡| 成人无码www在线看免费| 年轻女教师hd中字3| 黑人猛精品一区二区三区| 国产成人免费| 精品无码国产日韩制服丝袜| 亚洲日本国产精品一区| 欧美人成精品网站播放| 无码人妻丰满熟妇啪啪| 国产一区二区三区无遮挡| 亚洲综合在线日韩av| 性欧美老妇另类xxxx| 麻豆精品一区二区三区蜜臀| 国产一区二区高清不卡| 久热中文字幕在线精品观| 亚洲永久精品日韩成人av| 国产无人区码一区二区| 亚洲三区在线观看无套内射| 国产偷人妻精品一区二区在线| 亚洲春色在线视频| 娇小萝被两个黑人用半米长| 激情综合五月| 亚洲国产精品一区二区久| 久久男人av资源站| 大屁股国产白浆一二区| 国产精品久久无中文字幕| 九九热爱视频精品| 久久综合伊人77777| 东方四虎av在线观看| 久久九九兔免费精品6|