项目结构:

准备数据

CREATE TABLE `demo_entity` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`age` bigint(20) DEFAULT ‘0’,
`cdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`udate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

1、存储过程的调用
存储过程主要返回三类

1、返回数值的存储过程,其执行完后返回一个值,例如数据库中执行一个有返回值的函数或命令。
2、返回记录集的存储过程:执行结果是一个记录集,例如,从数据库中检索出符合某一个或几个条件的记录。
3、行为存储过程,用来实现数据库的某个功能,而没有返回值,例如在数据库中的更新和删除操作。
1、接收一个返回值
1.1、创建存储过程
1.2、返回out变量

DROP PROCEDURE IF EXISTS pro;
CREATE PROCEDURE pro (
IN userId INT,
OUT userCount INT
)
BEGIN
DECLARE user_name VARCHAR (64);
#SELECT d.name FROM demo_entity d WHERE d.id = userId INTO user_name;
#INSERT INTO demo_entity (name) VALUES (user_name);
SELECT COUNT(*) FROM demo_entity INTO userCount;
end;

call pro(1,@userCount);
select @userCount ;

1.2、返回集合和out变量

DROP PROCEDURE IF EXISTS pro_one_list;
CREATE PROCEDURE pro_one_list (
IN p_name varchar(20),
OUT userCount INT
)
BEGIN
select count(*) from demo_entity d where d.name = p_name into userCount ;
SELECT * FROM demo_entity d where d.name = p_name;
end;

call pro_one_list(‘小芳’,@userCount);
select @userCount ;

1.3、返回多列集合和变量

drop procedure IF EXISTS pro_many_list ;
CREATE PROCEDURE pro_many_list (
IN one_name varchar(20),
IN two_name varchar(20),
OUT userCount INT
)
BEGIN
select count(*) from demo_entity d where d.name = one_name into userCount ;
SELECT d.* FROM demo_entity d where d.name = one_name;
SELECT e.* FROM demo_entity e where e.name = two_name;
end;

call pro_many_list(‘小芳’,’小小芳’,@userCount);
select @userCount ;

2、mybatis xml 配置

out 中必须制定jdbc类型,因为存储过程会对它进行赋值操作

              call pro (              #{userId,   mode=IN},              #{userCount,mode=OUT,jdbcType=INTEGER}      )            call pro_one_list (              #{userName, mode=IN},              #{userCount,mode=OUT,jdbcType=INTEGER}      )                                                                call pro_many_list (              #{oneName, mode=IN},              #{twoName, mode=IN},              #{userCount,mode=OUT,jdbcType=INTEGER}      )   

3、mapper接口

@Mapperpublic interface DemoEntityMapper {    /**     * 1、获取 存储过程out参数值     * @param map     * @return     */    void procedureGetOut(Map map);    /**     * 2、获取 存储过程的结果集合-只有一个     * @param map     * @return     */    List procedureGetOneList(Map map) ;    /**     * 3、获取 存储过程的 获取多个集合 使用了泛型,有可能集合中是不同的     * @param     * @return     */    List<List> procedureGetManyList(Map map);}

4、业务层

@Servicepublic class ProcedureServiceImpl implements IProcedureService {    @Autowired    DemoEntityMapper demoEntityMapper;    @Override    public Integer procedureGetOut(Long id) {        Map param = new HashMap();        param.put("userId", id) ;        //执行完存储过程会自动更新这个map值        demoEntityMapper.procedureGetOut(param);        return Integer.valueOf(param.get("userCount").toString());    }    /**     * 2、获取 存储过程的结果集合-只有一个     * @param name     * @return     */    @Override    public List procedureGetOneList(String name) {        Map param = new HashMap();        param.put("userName", name) ;        //获取结果集        List list  = demoEntityMapper.procedureGetOneList(param);        System.out.println(Integer.valueOf(param.get("userCount").toString()));        return list;    }    /**     * 3、获取 存储过程的 获取多个集合 使用了泛型,有可能集合中是不同的     * @param     * @return     */    @Override    public List<List> procedureGetManyList(String oneName, String twoName) {        Map param = new HashMap();        param.put("oneName", oneName) ;        param.put("twoName", twoName) ;        List<List> lists =   demoEntityMapper.procedureGetManyList(param) ;        System.out.println("数组大小"+lists.size());        System.out.println("某个数量"+Integer.valueOf(param.get("userCount").toString()));        return lists;    }}

5、控制层

@RestController@RequestMapping("/procedure")public class ProcedureController {    @Autowired    IProcedureService procedureService;    @GetMapping("/procedureGetOut")    @ResponseBody    public String  procedureGetOut(Long id){        Integer integer = procedureService.procedureGetOut(id);        return String.valueOf(integer);    }    /**     * @Author     * @Description //TODO 获取返回结果集     * @Date     * @Param     * @return     **/    @GetMapping("procedureGetOneList")    @ResponseBody    public List procedureGetOneList(String name){        return procedureService.procedureGetOneList(name);    }    /**     * @Author     * @Description //TODO 获取返回结果集(多个)     * @Date     * @Param     * @return     **/    @GetMapping("procedureGetManyList")    @ResponseBody    public List procedureGetManyList(String oneName,String twoName){        return procedureService.procedureGetManyList(oneName,twoName);    }}

6、application.properties配置文件

server.port=9090spring.datasource.url=jdbc:mysql://localhost:3306/procedurespring.datasource.username=rootspring.datasource.password=root#数据库驱动#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# 打开驼峰命名规则mybatis.configuration.map-underscore-to-camel-case=true# classpath和classpath*的区别#classpath:只会到你的class路径中查找找文件。#classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。#注意: 用classpath*:需要遍历所有的classpath,所以加载速度是很慢的;因此,在规划的时候,应该尽可能规划好资源文件所在的路径,尽量避免使用classpath*。#接口的配置文件的位置-映射用mybatis.mapper-locations=classpath*:com/example/cache/mapper/xml/*Mapper.xml# mapper包下打印日志logging.level.com.example.cache.mapper=debugspring.redis.host=127.0.0.1spring.redis.port=6379spring.redis.password=''#debug=true

7、pom文件依赖

                    org.springframework.boot            spring-boot-starter-data-redis                            org.springframework.boot            spring-boot-starter-web                            org.mybatis.spring.boot            mybatis-spring-boot-starter            2.2.2                            mysql            mysql-connector-java            runtime                            org.projectlombok            lombok            true                            org.springframework.boot            spring-boot-starter-test            test                            io.projectreactor            reactor-test            test            

调用回报错:

报错问题:
mapper绑定异常 nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xxx.xxxx.mapper.UserMapper.getAllUser] with root cause

背景:

mapper接口和**mapper.xml映射文件**在同一个包下。

在看到 **Invalid bound statement (not found)**后,提示未找到mapper映射文件,然后打开编译后的target包或生成的jar包后,找到mapper映射文件存放位置,发现编译后的jar包内并没有此映射文件,进而将问题指向到Maven编译的过程中没有将普通配置文件编译进jar包内。

报错原因:

​ 由于我把mapper映射文件放在mapper接口的同一包里,并没有放在resources目录下,导致通过Maven编译后没有把除Java以外的映射文件、配置文件编译到target和jar包内,在运行时,调用mapper映射文件时,发现在同一个目录下没有找到mapper映射文件而报错。

​ 我们知道Maven是根据pom.xml执行任务,其中build标签描述了如何来编译及打包项目,而具体的编译和打包工作是通过build中配置的 plugin 来完成。而对于resources目录下资源,往往不是代码(.properties或XML配置文件),无需编译,所以在构建过程中往往会将资源文件从源路径直接复制到指定的目标路径。

​ src/main/java和src/test/java这两个目录中的所有*.java文件会分别在comile和test-comiple阶段被编译,编译结果分别放到了target/classes和targe/test-classes目录中,但是这两个目录中的其他文件都会被忽略掉。

解决办法:

需要在你的项目的pom文件中添加一下配置

                                    src/main/java                            **/*.yml                **/*.xml                        false                                    src/main/resources                            **/*.yml                **/*.properties