zoukankan      html  css  js  c++  java
  • 通过手动抛自定义异常实现spring事务回滚

    spring默认事务管理:默认当一个方法出现RunTimeException(运行期异常)时会自动回滚事务。

    有些时候,我们需要从业务上对spring事务进行控制,这时候,如果用spring的默认事务管理,事务没有回滚就达不到我们所期望的结果。

    demo用的spring+mybatis+springmvc+mysql。

    解决方法:

    applicationContext-service.xml 中增删改方法加上rollback-for="MyException",当方法抛出自定义异常被spring接收,会回滚事务。

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:task="http://www.springframework.org/schema/task"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd 
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-4.2.xsd 
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
            http://www.springframework.org/schema/task
               http://www.springframework.org/schema/task/spring-task-4.2.xsd
            http://code.alibabatech.com/schema/dubbo        
            http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
            
            
            <!-- 配置  扫描   @Service -->
            <context:component-scan base-package="com.educloud.service"/>
            
            <!-- 事务管理器 -->
        <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="save*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="insert*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="add*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="create*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="delete*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="update*" propagation="REQUIRED" rollback-for="MyException"/>
                <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            </tx:attributes>
        </tx:advice>
        <!-- 切面 -->
        <aop:config>
            <aop:advisor advice-ref="txAdvice"
                pointcut="execution(* com.educloud.service.impl.*.*(..))" />
        </aop:config>
            
            
    </beans>
    View Code

    MyException 自定义异常类:

    public class MyException extends Exception {
    
    private String message;
    
    public String getMessage() {
    return message;
    }
    
    public void setMessage(String message) {
    this.message = message;
    }
    
    public MyException(String message) {
    super();
    this.message = message;
    }
    
    public MyException() {
    super();
    }
    
    public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    super(message, cause, enableSuppression, writableStackTrace);
    }
    
    public MyException(String message, Throwable cause) {
    super(message, cause);
    }
    
    public MyException(Throwable cause) {
    super(cause);
    }
    View Code

    ProMapper.java

    package com.educloud.mapper;
    
    import com.educloud.pojo.Pro;
    
    public interface ProMapper {
        
    
        int deletePro(Integer id);
        
        int insertPro(Pro record);
    
        Pro selectPro(Integer id);
    
        int updatePro(Pro record);
    
    }
    View Code

    ProMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.educloud.mapper.ProMapper" >
      <resultMap id="BaseResultMap" type="com.educloud.pojo.Pro" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="pro_name" property="proName" jdbcType="VARCHAR" />
        <result column="data_flag" property="dataFlag" jdbcType="INTEGER" />
        <result column="create_date" property="createDate" jdbcType="TIMESTAMP" />
      </resultMap>
      
      <sql id="Base_Column_List" >
        id, pro_name, data_flag, create_date
      </sql>
     
      <select id="selectPro" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
        select 
        <include refid="Base_Column_List" />
        from pro
        where id = #{id,jdbcType=INTEGER}
      </select>
      
      <delete id="deletePro" parameterType="java.lang.Integer" >
        delete from pro
        where id = #{id,jdbcType=INTEGER}
      </delete>
      
      
      <insert id="insertPro" parameterType="com.educloud.pojo.Pro" >
          <selectKey keyProperty="id" resultType="Integer" order="AFTER">
              select LAST_INSERT_ID()
          </selectKey>
          
        insert into pro
        <trim prefix="(" suffix=")" suffixOverrides="," >
          <if test="proName != null and proName != '' " >
            pro_name,
          </if>
          <if test="dataFlag != null" >
            data_flag,
          </if>
          <if test="createDate != null" >
            create_date,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
          <if test="proName != null and proName != '' " >
            #{proName,jdbcType=VARCHAR},
          </if>
          <if test="dataFlag != null" >
            #{dataFlag,jdbcType=INTEGER},
          </if>
          <if test="createDate != null" >
            #{createDate,jdbcType=TIMESTAMP},
          </if>
        </trim>
      </insert>
      
      
      
      <update id="updatePro" parameterType="com.educloud.pojo.Pro" >
        update pro
        <set >
          <if test="proName != null" >
            pro_name = #{proName,jdbcType=VARCHAR},
          </if>
          <if test="dataFlag != null" >
            data_flag = #{dataFlag,jdbcType=INTEGER},
          </if>
          <if test="createDate != null" >
            create_date = #{createDate,jdbcType=TIMESTAMP},
          </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
      </update>
     
    </mapper>
    View Code

    ProDetailMapper.java

    package com.educloud.mapper;
    
    import com.educloud.pojo.ProDetail;
    
    public interface ProDetailMapper {
    
        int deleteProDetail(Integer id);
    
    
        int insertProDetail(ProDetail record);
    
    
        ProDetail selectProDetail(Integer id);
    
      
        int updateProDetail(ProDetail record);
    
    }
    View Code

    ProDetailMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.educloud.mapper.ProDetailMapper" >
      <resultMap id="BaseResultMap" type="com.educloud.pojo.ProDetail" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="pro_detail_name" property="proDetailName" jdbcType="VARCHAR" />
        <result column="data_flag" property="dataFlag" jdbcType="INTEGER" />
        <result column="create_date" property="createDate" jdbcType="TIMESTAMP" />
        <result column="pro_id" property="proId" jdbcType="INTEGER" />
      </resultMap>
      
      <sql id="Base_Column_List" >
        id, pro_detail_name, data_flag, create_date, pro_id
      </sql>
    
      
      <select id="selectProDetail" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
        select 
        <include refid="Base_Column_List" />
        from pro_detail
        where id = #{id,jdbcType=INTEGER}
      </select>
      
      <delete id="deleteProDetail" parameterType="java.lang.Integer" >
        delete from pro_detail
        where id = #{id,jdbcType=INTEGER}
      </delete>
      
      
      <insert id="insertProDetail" parameterType="com.educloud.pojo.ProDetail" >
        insert into pro_detail
        <trim prefix="(" suffix=")" suffixOverrides="," >
          
          <if test="proDetailName != null and proDetailName != '' " >
            pro_detail_name,
          </if>
          <if test="dataFlag != null" >
            data_flag,
          </if>
          <if test="createDate != null" >
            create_date,
          </if>
          <if test="proId != null" >
            pro_id,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
          
          <if test="proDetailName != null and proDetailName != '' " >
            #{proDetailName,jdbcType=VARCHAR},
          </if>
          <if test="dataFlag != null" >
            #{dataFlag,jdbcType=INTEGER},
          </if>
          <if test="createDate != null" >
            #{createDate,jdbcType=TIMESTAMP},
          </if>
          <if test="proId != null" >
            #{proId,jdbcType=INTEGER},
          </if>
        </trim>
      </insert>
      
      
      
      <update id="updateProDetail" parameterType="com.educloud.pojo.ProDetail" >
        update pro_detail
        <set >
          <if test="proDetailName != null" >
            pro_detail_name = #{proDetailName,jdbcType=VARCHAR},
          </if>
          <if test="dataFlag != null" >
            data_flag = #{dataFlag,jdbcType=INTEGER},
          </if>
          <if test="createDate != null" >
            create_date = #{createDate,jdbcType=TIMESTAMP},
          </if>
          <if test="proId != null" >
            pro_id = #{proId,jdbcType=INTEGER},
          </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
      </update>
      
    </mapper>
    View Code

    ProService.java

    package com.educloud.service;
    
    import com.educloud.pojo.Pro;
    import com.educloud.utils.MyException;
    
    public interface ProService {
        
        int deletePro(Integer id) throws MyException;
        
        int insertPro(String proStr) throws MyException;
    
        Pro selectPro(Integer id) throws MyException;
    
        int updatePro(Pro record) throws MyException;
    
    }
    View Code

    ProController.java

    package com.educloud.controller;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.educloud.pojo.Pro;
    import com.educloud.service.ProService;
    import com.educloud.utils.MyException;
    
    @Controller
    public class ProController {
        
        @Autowired
        private ProService proService;
        
        @RequestMapping(value="/insertPro")
        @ResponseBody
        public Map<String, Object> insertPro(String proStr){
            //模拟前台数据
            proStr = "{"pro": {"proName": "体"},"proDetailList": [{"proDetailName": "身高"},{"proDetailName": ""},{"proDetailName": "健康状况"}]}";
            Map<String, Object> map = new HashMap<>();
            String mString = "";
            try {
                int count = proService.insertPro(proStr);
                mString = "新增成功!";
            } catch (MyException e) {
                mString = e.getMessage();
            }
            map.put("msg", mString);
            return map;
        }
    
    }
    View Code

    ProServiceImpl.java

    方法抛出自定义异常  thorw new MyException();

    package com.educloud.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.educloud.mapper.ProDetailMapper;
    import com.educloud.mapper.ProMapper;
    import com.educloud.pojo.Pro;
    import com.educloud.pojo.ProDetail;
    import com.educloud.service.ProService;
    import com.educloud.utils.MyException;
    
    @Service
    public class ProServiceImpl implements ProService {
        
        @Autowired
        private ProMapper proMapper;
        
        @Autowired
        private ProDetailMapper proDetailMapper;
    
        @Override
        public int insertPro(String proStr) throws MyException{
            // proStr = "{"pro": {"proName": "体"},"proDetailList": [{"proDetailName": "身高"},{"proDetailName": ""},{"proDetailName": "健康状况"}]}";
            
            //把json字符串转为json对象
            JSONObject object = JSONObject.parseObject(proStr);
            //获得pro评价指标对象
            JSONObject proObj = object.getJSONObject("pro");
            Pro pro = new Pro();
            pro.setProName(proObj.getString("proName"));
            int count = 0;
            count = proMapper.insertPro(pro);
            if (count ==0) {
                throw new MyException("新增指标失败!");
            }
            //获得proDetail评价指标明细list
            JSONArray proDetailList = object.getJSONArray("proDetailList");
            ProDetail proDetail = null;
            int count1 = 0;
            
            //方式一:
            for (int i = 0; i < proDetailList.size(); i++) {
                //获得proDetail评价指标明细list每一条数据
                JSONObject proDetailObj = proDetailList.getJSONObject(i);
                proDetail = new ProDetail();
                proDetail.setProDetailName(proDetailObj.getString("proDetailName"));
                proDetail.setProId(pro.getId());
                try {
                    count1 += proDetailMapper.insertProDetail(proDetail);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //抛自定义异常进行事务控制
            if (count1 < proDetailList.size()) {
                throw new MyException("新增指标明细失败!");
            }
            return 1;
            
            //方式二
    //        for (int i = 0; i < proDetailList.size(); i++) {
    //            /**获得proDetail评价指标明细list每一条数据*/
    //            JSONObject proDetailObj = proDetailList.getJSONObject(i);
    //            proDetail = new ProDetail();
    //            proDetail.setProDetailName(proDetailObj.getString("proDetailName"));
    //            proDetail.setProId(pro.getId());
    //            count1 += proDetailMapper.insertProDetail(proDetail);
    //        }
    //        int resultNum = proDetailList.size() + 1; 
    //        /**抛自定义异常进行事务控制*/
    //        if(resultNum == count+count1){
    //            return 1;
    //        }else{
    //            throw new MyException("新增失败!");
    //        }
            
        }
        
        @Override
        public int deletePro(Integer id) throws MyException{
            return proMapper.deletePro(id);
        }
    
        
        @Override
        public Pro selectPro(Integer id) throws MyException{
            return proMapper.selectPro(id);
        }
    
        @Override
        public int updatePro(Pro record) throws MyException{
            return proMapper.updatePro(record);
        }
    
    }
    View Code

    Pro.java

    package com.educloud.pojo;
    
    import java.util.Date;
    
    public class Pro {
        private Integer id;
    
        private String proName;
    
        private Integer dataFlag;
    
        private Date createDate;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getProName() {
            return proName;
        }
    
        public void setProName(String proName) {
            this.proName = proName == null ? null : proName.trim();
        }
    
        public Integer getDataFlag() {
            return dataFlag;
        }
    
        public void setDataFlag(Integer dataFlag) {
            this.dataFlag = dataFlag;
        }
    
        public Date getCreateDate() {
            return createDate;
        }
    
        public void setCreateDate(Date createDate) {
            this.createDate = createDate;
        }
    
        @Override
        public String toString() {
            return "Pro [id=" + id + ", proName=" + proName + ", dataFlag=" + dataFlag + ", createDate=" + createDate + "]";
        }
        
        
    }
    View Code

    项目百度网盘地址: https://pan.baidu.com/s/1L_zMjmqu-gXRqifcVEfQ1A  提取码: idii 

  • 相关阅读:
    WinDbg符号表设置的基础
    Mysql的用户管理与授权
    Django的models由数据库表生成
    Spring框架第一天(搭建项目)
    Python中的参数
    Java集合
    Mysql的锁
    # django通过操作admin对原有的数据库进行操作
    数据库连接池与SQL工具类
    MySql的事务及数据的导入导出
  • 原文地址:https://www.cnblogs.com/javalanger/p/10912482.html
Copyright © 2011-2022 走看看