如何使用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
SET @r_result = 3
-- 执行存储过程
CALL execute_seckill(1003,1998998988,NOW(),@r_result);
-- 获取结果
select @r_result
-- 存储过程
-- 1.存储过程优化:
-- 2.不要过度依赖存储过程
-- 3.简单逻辑可以应用存储过程
mybatis配置文件的写法(一个有模有样的存储过程有in和out参数):
它的接口:
/**
* 直接使用存储过程完成秒杀
* @param paramMap
*/
void killByProcedure(Map paramMap);
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都是项目中千锤百炼出来的工具类项目,很好用。可以看源码,确实方便。