中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決Spring事務管理配置文件問題

發布時間:2020-07-23 11:20:12 來源:億速云 閱讀:173 作者:小豬 欄目:編程語言

這篇文章主要為大家展示了如何解決Spring事務管理配置文件問題,內容簡而易懂,希望大家可以學習一下,學習完之后肯定會有收獲的,下面讓小編帶大家一起來看看吧。

在開發中,遇到了sql語句報錯,但是并沒有回滾的情況。

經過幾天的排查,終于找到了事務沒有回滾的原因。

原來的項目用的是informix的數據庫,原來針對事務回滾的機制都是好用的。我本地用的是mysql數據庫。

先將程序代碼與spring-mybatis.xml配置文件拿過來:

1、程序代碼:

這個問題是在驗證增刪改查返回值時發現的。

兩個操作,刪除時,因為關聯了外鍵,所以會報錯,此時正常情況更新的語句也會回滾,但是并沒有。

/**
   *@Author: Administrator on 2020/3/12 15:15
   *@param:
   *@return:
   *@Description:查詢同步情況
   */
  @Override
  public PageInfo getSyncstatusPages(Syncstatus vo, int pageNo, int pageSize) {
    PageHelper.startPage(pageNo, pageSize);


    /* //查看增刪改查的返回值
    //1新增:返回值自己定義,可以是void,int
    //1-1新增一條數據:插入成功,返回值為1
    int insert_success1 = yylfHttpServletMapper.insert("8", "2", "1");
    //1-2新增多條數據:插入成功,返回值為插入的數據條數,當有一條數據錯誤時,所有數據都會插入失敗
    int insert_success2 = yylfHttpServletMapper.insert_duotiao("7");
    String insert_success3 = yylfHttpServletMapper.insert_duotiao_String("7");//不支持返回值為String類型
    //1-3新增一條數據:插入失敗:主鍵沖突,會直接報異常
    int insert_failed = yylfHttpServletMapper.insert("1", "2", "1");
    //1-4插入null:屬性為null,如果表中所有字段允許為null,插入一條所有值均為null的數據
    Syncstatus syncstatus1 = null;
    yylfHttpServletMapper.insertSyncstatus(syncstatus1);
    //1-5插入一個沒有賦值的對象:屬性為null,如果表中所有字段允許為null,插入一條所有值均為null的數據
    Syncstatus syncstatus2 = new Syncstatus();
    yylfHttpServletMapper.insertSyncstatus(syncstatus2);*/


    /*//2刪除:返回值自己定義,可以是void,int
    //2-1刪除成功:沒有數據:返回值為0
    int delete_success1 = yylfHttpServletMapper.delete("0");
    //2-2刪除成功:有多條數據:返回值為刪除的數據條數
    int delete_success2 = yylfHttpServletMapper.delete_systemcode("2");*/
    //2-3刪除失敗:例如有外鍵:報異常


    //3更新:返回值自己定義,可以是void,int
    //3-1更新成功:沒有數據,返回值為0
    //int update_no = yylfHttpServletMapper.update_no("0");
    //3-2更新成功:有多條數據,返回更新的數據條數
    int update_duotiao = yylfHttpServletMapper.update_duotiao_systemcode("2");
    int delete_fail = yylfHttpServletMapper.delete("1");
    //3-3更新失敗:例如有外鍵,報異常
    //int update_fail = yylfHttpServletMapper.update_fail("1");

    //4查詢
    //4-1 沒數:String 類型返回null
    //Object object = yylfHttpServletMapper.select("0");
    //4-1 沒數:集合 類型返回[]空集合
    //Syncstatus syncstatus3 = new Syncstatus();
    //syncstatus3.setStatus("7");
    //List<Syncstatus> page0 = yylfHttpServletMapper.getSyncstatusList(syncstatus3);
    //4-1 沒數:int 類型返回null,如果定義為int會報錯。因為沒數時返回null,可以將返回類型改為String
    //String i = yylfHttpServletMapper.select_int(0);
    //4-1:當返回值為對象時,若返回值為空,則返回null
    //4-2 有數
    List<Syncstatus> pages = yylfHttpServletMapper.getSyncstatusList(vo);
    return new PageInfo<Syncstatus>(pages);
  }

2、對數據庫的操作:

<update id="update_duotiao_systemcode">
  UPDATE aaa SET systemcode = '3' WHERE systemcode = #{systemcode,jdbcType=VARCHAR}
 </update>

<delete id="delete">
  delete from aaa where uuid = #{uuid,jdbcType=VARCHAR}
 </delete>

3、配置文件:

<&#63;xml version="1.0" encoding="UTF-8"&#63;>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  http://www.springframework.org/schema/tx
  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource">
    <constructor-arg ref="dataSourceTarget"/>
  </bean>

  <!-- 定義使用dbcp2連接池的數據源
      此處使用自定義的數據源,將用戶名與密碼解密處理
   -->
  <bean id="dataSourceTarget" class="com.asd.common.jdbc.MyBasicDataSource" >
    <property name="url" value="${jdbc.url}"> </property>
    <property name="username" value="${jdbc.username}"> </property>
    <property name="password" value="${jdbc.password}"> </property>
    <property name="driverClassName" value="${jdbc.driverClassName}"> </property>
    <!-- informix-->
    <!--<property name="validationQuery" value="select count(*) from systables"> </property>-->
    <!-- mysql檢測方式 -->
     <property name="validationQuery" value="select 1"> </property>
    <!-- oracle檢測方式
    <property name="validationQuery" value="select 1 from dual"> </property> -->
  </bean>

  <!-- 配置SqlSessionFactoryBean -->
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 注入數據源 相關信息看源碼 -->
    <property name="dataSource" ref="dataSource" />
    <!-- 掃描的實體所在的包-->
    <property name="configLocation" value="classpath:mybatis.xml"/>
    <!-- mapper和resultmap配置路徑 -->
    <property name="mapperLocations">
      <list>
        <value>classpath:mybatis/*Mapper.xml</value>
      </list>
    </property>
  </bean>

  <!-- 自動掃描mapper接口,注入sqlsessionfactory -->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.asd.modules.dao"/>
  </bean>

  <!-- 啟用類掃描機制,通過元數據配置Service -->
  <context:component-scan base-package="com.asd">
    <context:include-filter type="regex"
                expression="com\.asd\.modules\.sevice\.impl\.*ServiceImpl" />
  </context:component-scan>

  <!-- mybatis事物配置 -->

  <context:annotation-config />
  <!-- ================================事務相關控制================================================= -->

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

  <tx:advice id="reinsAdvice" transaction-manager="transactionManager">
    <tx:attributes>

      <tx:method name="delete*" propagation="REQUIRED" read-only="false"
            rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />

      <tx:method name="insert*" propagation="REQUIRED" read-only="false"
            rollback-for="java.lang.RuntimeException" />
      <tx:method name="save*" propagation="REQUIRED" read-only="false"
            rollback-for="java.lang.RuntimeException" />

      <tx:method name="update*" propagation="REQUIRED" read-only="false"
            rollback-for="java.lang.Exception" />

      <tx:method name="find*" propagation="SUPPORTS" />
      <tx:method name="get*" propagation="SUPPORTS" />
      <tx:method name="select*" propagation="SUPPORTS" />
      <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
    </tx:attributes>
  </tx:advice>

  <aop:config>
    <!-- 把事務控制在Service層 -->
    <aop:pointcut id="reinsPointCut"
           expression="execution(* com.asd.modules.service.impl.*ServiceImpl.*(..))" />
    <aop:advisor pointcut-ref="reinsPointCut"
           advice-ref="reinsAdvice" />
  </aop:config>

</beans>

4、數據庫語句:

-- 創建aaa表用來驗證增刪改查的返回值
CREATE TABLE `reserve`.`aaa` (
 `uuid` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 `systemcode` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 `status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 
 PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;


-- 創建bbb表用來關聯aaa的uuid作外鍵
CREATE TABLE `reserve`.`bbb` (
 `uuid` char(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 `systemcode` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 `status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 
 PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

alter table bbb add constraint FK_T_POSITI_REFERENCE_T_COMPAN foreign key (uuid)references 
aaa (uuid);

insert into bbb (uuid,systemcode,status)value ('1','2','2');

-- 驗證事支持
DELETE from aaa where uuid != '1';
insert into aaa (uuid,systemcode,status)value ('2','2','2');
SELECT * FROM aaa;

排查過程共查找了下述方面:

1、排除數據庫原因:

如何解決Spring事務管理配置文件問題

查看mysql數據庫是支持事務的;而且用informix數據庫進行了驗證,同樣沒有回滾。

2、驗證了impl的類型等均為問題。

3、查看了事務的配置信息也正確好用。

4、驗證了系統其它的一些方法,發現是支持事務的。

5、將這兩個語句放到其它方法里也好用。

6、事務是在service層處理的,在控制層也加了異常捕獲(這個操作并不會影響事務回滾,即使不catch,也會回滾的)

最終鎖定問題原因:是因為方法名稱的問題。

當將方法名改成其它的,不以get開頭,不報錯。

這個問題很坑,因為本以為為配置文件中的get*,會使這個方法的事務起作用,誰知道恰恰get*的這個配置雖然起作用了,但是結果卻是事務不回滾,在將該配置改為

<tx:method name="get*" propagation="SUPPORTS" rollback-for="java.lang.Exception"/>

也沒有用,最后將其注釋掉,事務回滾。走了下面的配置:

<tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />

需要注意的是tx:method 的name屬性指的是方法名。

將SUPPORTS改為REQUIRED后,事務也進行回滾。最終得到原因:是因為propagation的配置信息不正確。

拓展:

一、在聲明式的事務處理中,要配置一個切面,其中就用到了propagation,表示打算對這些方法怎么使用事務,是用還是不用,其中propagation有七種配置,REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。默認是REQUIRED。

二、Spring中七種Propagation類的事務屬性詳解:

  • REQUIRED:支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
  • SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行。
  • MANDATORY:支持當前事務,如果當前沒有事務,就拋出異常。
  • REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。
  • NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
  • NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
  • NESTED:支持當前事務,如果當前事務存在,則執行一個嵌套事務,如果當前沒有事務,就新建一個事務。

三、注意.

這個配置將影響數據存儲,必須根據情況選擇。

問題往往出現在你忽略的地方。

以上就是關于如何解決Spring事務管理配置文件問題的內容,如果你們有學習到知識或者技能,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永修县| 云南省| 澄江县| 绥德县| 图们市| 澄城县| 望谟县| 连州市| 靖宇县| 深水埗区| 涪陵区| 建湖县| 达州市| 定襄县| 织金县| 偏关县| 进贤县| 河源市| 馆陶县| 诸暨市| 红安县| 潜江市| 象州县| 内江市| 揭阳市| 化州市| 胶州市| 新野县| 穆棱市| 桐乡市| 前郭尔| 麻栗坡县| 桂林市| 星子县| 武功县| 六枝特区| 广水市| 黔东| 丽水市| 德钦县| 芜湖县|