如何使用mybatis调用存储过程

9 篇文章 0 订阅
3 篇文章 0 订阅

如何使用mybatis调用存储过程

先提供一个秒杀逻辑(https://github.com/cdefgab1234/seckill)的存储过程:

--秒杀执行存储过程
DELIMITER $$
-- 运行第二次,这是为了能多次运行
DROP PROCEDURE IF EXISTS `execute_seckill`$$
-- 参数: in 输入参数; out 输出参数
-- row_count() 返回上一条修改类型的(delete,insert,update)sql影响的行数
-- row_count(); 0:未修改数据  >0影响行数  <0 sql错误,未执行sql
CREATE DEFINER=`root`@`localhost` PROCEDURE `execute_seckill`(IN v_seckill_id BIGINT,IN v_phone BIGINT,IN v_kill_time TIMESTAMP,OUT r_result INT)
BEGIN
        DECLARE insert_count INT DEFAULT 0;
        START TRANSACTION;
        INSERT IGNORE success_killed(seckill_id,user_phone,create_time)
          VALUES(v_seckill_id,v_phone,v_kill_time);

        SELECT ROW_COUNT() INTO insert_count;
        IF (insert_count = 0) THEN
           ROLLBACK;
           SET r_result = -1;
        ELSEIF(insert_count<0) THEN
           ROLLBACK;
           SET r_result = -2;
        ELSE
           UPDATE seckill
           SET number=number-1
           WHERE seckill_id = v_seckill_id
            AND end_time > v_kill_time
            AND start_time < v_kill_time
            AND number > 0;

         SELECT ROW_COUNT() INTO insert_count;
	IF (insert_count=0) THEN
	    ROLLBACK;
	    SET r_result=0;
	ELSEIF (insert_count <0) THEN
	    ROLLBACK;
	    SET r_result = -2;
	ELSE
	    COMMIT;
	    SET r_result = 1;
	END IF;
        END IF;
    END$$

DELIMITER ;

START TRANSACTION; -- 一个小链接http://www.cnblogs.com/langtianya/p/4777662.html

sql调用存储过程语法(猴头符号是必须的)

SET @r_result = 3

-- 执行存储过程
CALL execute_seckill(1003,1998998988,NOW(),@r_result);
-- 获取结果
select @r_result

-- 存储过程
-- 1.存储过程优化:
-- 2.不要过度依赖存储过程
-- 3.简单逻辑可以应用存储过程
mybatis配置文件的写法(一个有模有样的存储过程有in和out参数):

<!--mybatis调用存储过程-->
    <select id="killByProcedure" statementType="CALLABLE">
        call execute_seckill(
         #{seckillId,jdbcType=BIGINT,mode=IN},
         #{phone,jdbcType=BIGINT,mode=IN},
         #{killTime,jdbcType=TIMESTAMP,mode=IN},
         #{result,jdbcType=INTEGER,mode=OUT}
        )
    </select>
它的接口:

/**
     * 直接使用存储过程完成秒杀
     * @param paramMap
     */
    void killByProcedure(Map<String, Object> paramMap);

@service层调用的方法:

 public SeckillExecution executeSeckillProcedure(long seckillId, long userPhone, String md5)  {
        if(md5==null || !md5.equals(getMd5(seckillId))){
            return new SeckillExecution(seckillId,SeckillStatEnum.DATA_REWRITE);
        }
        Date killTime = new Date();
        Map map = new HashMap();
        map.put("seckillId",seckillId);
        map.put("phone",userPhone);
        map.put("killTime",killTime);
        map.put("result",null);
        //执行存储过程,result被复制
        try {
            seckillDao.killByProcedure(map);
            int result = MapUtils.getInteger(map, "result", -2);
            if (result == 1) {
                SuccessKilled sk = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
                return new SeckillExecution(seckillId, SeckillStatEnum.SUCCESS, sk);
            } else {
                return new SeckillExecution(seckillId, SeckillStatEnum.stateOf(result));
            }
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            return new SeckillExecution(seckillId,SeckillStatEnum.INNER_ERROR);
        }

    }
MapUtils.getInteger();方法是commons-collection的一个方法:找map中键值为“result”的方法,null则为-2

和stringUntils都是项目中千锤百炼出来的工具类项目,很好用。可以看源码,确实方便。








  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值