一、什么是mysql存储过程

存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。MySQL 5.0 版本开始支持存储过程。

直白点就是,本该在service层完成的逻辑操作,直接放到数据库内完成了。

好处:减少了与数据进行连接完成操作的过程,提高了执行效率

缺点:增加了数据库的负担,且移植性较差

二、存储过程的语法

以添加部门的代码为例

DELIMITER $$
 
USE `vhr`$$
 
DROP PROCEDURE IF EXISTS `addDep`$$
 
CREATE DEFINER=`root`@`localhost` PROCEDURE `addDep`(IN depName VARCHAR(32),IN parentId INT,IN enabled BOOLEAN,OUT result INT,OUT result2 INT)
BEGIN
  DECLARE did INT;
  DECLARE pDepPath VARCHAR(64);
  INSERT INTO department SET NAME=depName,parentId=parentId,enabled=enabled;
  SELECT ROW_COUNT() INTO result;
  SELECT LAST_INSERT_ID() INTO did;
  SET result2=did;
  SELECT depPath INTO pDepPath FROM department WHERE id=parentId;
  UPDATE department SET depPath=CONCAT(pDepPath,'.',did) WHERE id=did;
  UPDATE department SET isParent=TRUE WHERE id=parentId;
END$$
 
DELIMITER ;
DELIMITER

定义
定义
为语句的结束符, 默认语句的结束符为";" 分号 ,防止语句写一句提交一句先设置为$$

USE `vhr`$$  使用数据库
DROP PROCEDURE IF EXISTS `addDep`$$   如果存在就删除addDep程序
CREATE DEFINER=`root`@`localhost` PROCEDURE `addDep`(IN depName VARCHAR(32),IN parentId INT,IN enabled BOOLEAN,OUT result INT,OUT result2 INT)    创建addDep程序 IN代表传入参数,OUT代表传出结果  
BEGIN 开始   END 结束
DECLARE 声明变量 
INSERT INTO department SET NAME=depName,parentId=parentId,enabled=enabled;  用传进来的参数添加一条语句
SELECT ROW_COUNT() INTO result;  查询刚才成功添加语句的行数  并把结果存入 result
   SELECT LAST_INSERT_ID() INTO did;  查询刚刚添加的语句 生成的id  并把结果存入did
   SET result2=did; 把did赋值给result2
   SELECT depPath INTO pDepPath FROM department WHERE id=parentId; 查询parentId的depPath  存入 pDepPath
   UPDATE department SET depPath=CONCAT(pDepPath,'.',did) WHERE id=did;  更新新添加的语句的 depPath, CONCAT(pDepPath,'.',did)拼接字符串
   UPDATE department SET isParent=TRUE WHERE id=parentId;  将父ID下的isParent设置为true

执行完成之后  数据库中显示创建的存储过程

三、controller、service、mapper层以及mapper.xml的语句

1、mapper.xml  

Statement的实现类:PreparedStatement 和 CallableStatement。

CALLABLE对应CallableStatement

call addDep()就是调用addDep方法 里面就是创建的时候 设置的输入参数 与输出结果

 <!--调用存储过程进行数据存储-->

<select id="addDep"  statementType="CALLABLE">
    call addDep(#{name,mode=IN,jdbcType=VARCHAR},#{parentId,mode=IN,jdbcType=INTEGER},#{enabled,mode=IN,jdbcType=BOOLEAN},
    #{result,mode=OUT,jdbcType=INTEGER},#{id,mode=OUT,jdbcType=INTEGER})
  </select>

2、mapper层、service层、controller层

其中controller层中值得说的一点是  传入的参数dep  会在执行完语句后 将存储过程返回的结果封装到dep里  不需要返回值 直接调用

//mapper层
void addDep(Department dep);
 
 
//service层
 public void addDepartment(Department dep) {
        dep.setEnabled(true);
        departmentMapper.addDep(dep);
  }
 
 
//controller层
 @PostMapping("/")
    public RespBean addDepartment(@RequestBody Department dep){
        departmentService.addDepartment(dep);
        if(dep.getResult() == 1){
            return RespBean.ok("添加成功",dep);
        }
        return RespBean.error("添加失败");
    }

四、测试结果fuji

"status": 200,
    "msg": "添加成功",
    "obj": {
        "id": 108,
        "name": "运维三部",
        "parentId": 92,
        "depPath": null,
        "enabled": true,
        "children": [],
        "result": 1,
        "parent": null
    }
}

 附加:删除部门的存储过程的语句

语句逻辑:先判断要删除的部门是否是父部门,如果是,删除失败,返回结果为-2

                  再判断该部门是否有员工,如果有删除失败

                  然后就是直接删除 并判断是否还存在parentId与删除部门相同的部门,如果不存在

                   将 父部门的isParent设置为false

DELIMITER $$
 
USE `vhr`$$
 
DROP PROCEDURE IF EXISTS `deleteDep`$$
 
CREATE DEFINER=`root`@`localhost` PROCEDURE `deleteDep`(IN did INT,OUT result INT)
BEGIN
  DECLARE ecount INT;
  DECLARE pid INT;
  DECLARE pcount INT;
  DECLARE a INT;
  SELECT COUNT(*) INTO a FROM department WHERE id=did AND isParent=FALSE;
  IF a=0 THEN SET result=-2;
  ELSE
  SELECT COUNT(*) INTO ecount FROM employee WHERE departmentId=did;
  IF ecount>0 THEN SET result=-1;
  ELSE
  SELECT parentId INTO pid FROM department WHERE id=did;
  DELETE FROM department WHERE id=did AND isParent=FALSE;
  SELECT ROW_COUNT() INTO result;
  SELECT COUNT(*) INTO pcount FROM department WHERE parentId=pid;
  IF pcount=0 THEN UPDATE department SET isParent=FALSE WHERE id=pid;
  END IF;
  END IF;
  END IF;
END$$
 
DELIMITER ;