• MyBatis调用存储过程


    MySQL存储过程

    DROP PROCEDURE IF EXISTS transferMoney;
    -- 实现转账功能的存储过程
    CREATE PROCEDURE transferMoney (
        IN fromUserId INT,    -- 付款方
        IN toUserId INT,    -- 收款方
        IN money DOUBLE,        -- 转账金额
            OUT state INT,            -- 状态
            OUT errorMsg VARCHAR(40)    -- 异常信息
    )    
    BEGIN
            SET state = 0;        -- 0表示正常,99表示异常
            START TRANSACTION;    -- 启用事务
    
            -- 先扣除付款人的金额
            UPDATE USER u SET u.money = u.money-money WHERE id = fromUserId;
                IF ROW_COUNT()=0 then  -- 如果影响记录为0,表示异常,标示为99
                    set state = 99;
                                    set errorMsg = CONCAT('付款人金额更新影响行数为0,fromUserId:',fromUserId);
                END IF;
    
            -- 再增加收款人的金额
            UPDATE USER u SET u.money = u.money+money WHERE id = toUserId;
                IF ROW_COUNT()=0 then  -- 如果影响记录为0,表示异常,标示为99
                    set state = 99;
                                    set errorMsg = CONCAT('收款人金额更新影响行数为0,toUserId:',toUserId);
                END IF;
            
            -- 如果运行正常则提交,否则,回滚
            IF state=0 then 
                COMMIT;
            ELSE 
                ROLLBACK;
            END IF;
    END;

     MyBatis映射文件UserMapper.xml

    <select id="transferMoney" statementType="CALLABLE" parameterType="java.util.HashMap">
            {
              call transferMoney (#{fromUserId,mode=IN,jdbcType=INTEGER},
                                #{toUserId,mode=IN,jdbcType=INTEGER},
                                #{money,mode=IN,jdbcType=DOUBLE},
                                #{state,mode=OUT,jdbcType=INTEGER},
                                #{errorMsg,mode=OUT,jdbcType=VARCHAR})
            }
    </select>

     UserServiceImpl.java代码

    @Override
         public void transferMoneyByProcedure(int fromUserId, int toUserId, double money) {
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("fromUserId", fromUserId);
            map.put("toUserId", toUserId);
            map.put("money", money);
            userDao.transferMoney(map);
            //存储过程完成转账,打印执行结果,存储过程返回的out参数state, errorMsg值会保存在map中。
            Logger.info(JSON.toJSONString(map));
            int state = Integer.parseInt(map.get("state").toString());
            if(state != 0) {
                System.out.println("转账异常:"+map.get("errorMsg"));
            }
    
        }

    UserServiceTest.java代码

        @Test
        public void testTransferMoneyByProcedure() {
            int fromUserId = 1;
            int toUserId = 3;
            userService.transferMoneyByProcedure(fromUserId, toUserId, 1001);
        }

    控制台结果

    [com.ssm.dao.UserDao.transferMoney] - ==>  Preparing: { call transferMoney (?, ?, ?, ?, ?) } 
    [com.ssm.dao.UserDao.transferMoney] - ==> Parameters: 1(Integer), 3(Integer), 1001.0(Double)
    [com.ssm.common.Logger] - {"toUserId":3,"state":99,"money":1001,"errorMsg":"收款人金额更新影响行数为0,toUserId:3","fromUserId":1}
    转账异常:收款人金额更新影响行数为0,toUserId:3
    [org.springframework.context.support.GenericApplicationContext] - Closing org.springframework.context.support.GenericApplicationContext@7da3f9e4: startup date [Sat Oct 24 14:50:09 GMT+08:00 2015]; root of context hierarchy

     数据库User表

     Spring事务配置

    <!-- 第一种配置事务的方式 ,tx-->
        <tx:advice id="txadvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />
                <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" />
                <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
                <tx:method name="*TX" propagation="REQUIRED" rollback-for="Exception"/>
                <!-- 存储过程都是自带了事务处理,所以这里配置NEVER了 -->
                <tx:method name="*Procedure" propagation="NEVER" rollback-for="Exception"/>
                <tx:method name="*" propagation="REQUIRED" read-only="true"/>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
            <aop:pointcut id="serviceMethod" expression="execution(* com.ssm.service.*.*(..))"/>
            <aop:advisor pointcut-ref="serviceMethod" advice-ref="txadvice"/>
        </aop:config>
  • 相关阅读:
    Hackerrank alien-flowers(数学公式)
    Hackerrank manasa-and-combinatorics(数学推导)
    Codeforces 314B(倍增)
    Codeforces Round #403(div 2)
    Mutual Training for Wannafly Union #6
    几道splay
    高数(A)下 第十章
    Bestcoder #92
    codevs1700 施工方案第二季
    poj2631
  • 原文地址:https://www.cnblogs.com/cocoat/p/4905226.html
Copyright © 2020-2023  润新知