效果
1、结果集的大小代表返回多少个数据表记录,例如在存储过程中有两个 SELECT * 语句,则结果集大小为 2 。
2、结果集中的每一个数据表作为一个 List<?>,每一条记录为一个 Object 泛型。
3、存储过程中输出的参数 Msg Out 也可以通过 Map 读取。
数据表
# use Mysql 8.0
CREATE TABLE `TestUser` (
`id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
`username` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8mb4_0900_ai_ci'
ENGINE=InnoDB
;
CREATE TABLE `TestRight` (
`id` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
`userId` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
`userRight` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8mb4_0900_ai_ci'
ENGINE=InnoDB
;
1、创建用户表
2、创建用户权限表
3、往数据表写入模拟数据
存储过程
CREATE DEFINER=`root`@`%` PROCEDURE `MyBatisTestPro`(
IN `UserId` VARCHAR(50),
OUT `Msg` VARCHAR(50)
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT '返回多个结果集'
BEGIN
SELECT * FROM `demo`.`TestRight` WHERE userId = UserId;
SELECT * FROM `demo`.`TestUser` WHERE id = UserId;
SELECT 'OK' INTO Msg;
END
1、返回用户信息
2、返回用户权限信息
3、返回响应参数 Msg
主要 POM 依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
1、mybatis-plus 启动依赖和核心依赖
2、mysql 依赖
yml 配置
spring:
datasource:
url: jdbc:mysql://localhost:3307/demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456789
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
1、配置数据源
2、配置 mybatis 映射文件
MybatisConfig
package com.example.demo.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.example.demo.dao")
public class MybatisConfig {
}
1、扫描 mapper 文件
Mapper
package com.example.demo.dao;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface TestDao {
/**
* 调用 SP 测试,通过 List 接收多个结果集
* 外层List代表有 N 个结果集
* 里层List代表第 X 个结果集有 M 条数据
* ?代表泛型,按 Object 接收,可以替换成 Map<String,Object>
* @param map
* @return
*/
List<List<Map<String,Object>>> sptest(Map<String,Object> map);
}
1、测试 SP 接口
XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.TestDao">
<resultMap id="Map1" type="java.util.HashMap">
</resultMap>
<resultMap id="Map2" type="java.util.HashMap">
</resultMap>
<select id="sptest" resultType="java.util.List" resultMap="Map1,Map2" parameterType="Map" statementType="CALLABLE" >
{CALL MyBatisTestPro(#{UserId,mode=IN,jdbcType=VARCHAR},#{Msg,mode=OUT,jdbcType=VARCHAR})}
</select>
</mapper>
1、调用存储过程,注意结果集由 HashMap 接收 ,多个结果集则需要多个 Map 接收
2、注意传入参数为 Map ,通过 key value 键值对去匹配存储过程的参数
3、注意 statementType 为 CALLABLE 表明调用的是存储过程
4、对于存储过程的参数需要指定 mode 为 IN 还是为 OUT
ServiceImpl
package com.example.demo.service.impl;
import com.example.demo.dao.TestDao;
import com.example.demo.service.TestService;
import com.example.demo.utils.JacksonUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service("testService")
public class TestServiceImpl implements TestService {
@Resource
private TestDao testDao;
@Override
public void testsp() throws IOException {
System.out.println(LocalDateTime.now().toString());
Map<String, Object> map = new HashMap<String, Object>();
map.put("UserId", "51fce378-4e93-11ed-b86f-0242ac110002");
System.out.println("===> 执行存储过程:" + LocalDateTime.now().toString());
List<List<Map<String, Object>>> sptest = testDao.sptest(map);
System.out.println("===> 结果集大小:" + sptest.size());
System.out.println("结果集:");
for (List<Map<String, Object>> objects : sptest) {
//System.out.println(JacksonUtil.toJsonString(objects));
if (objects.size() > 1) {
for (Map<String, Object> obj : objects) {
System.out.println(JacksonUtil.toJsonString(obj));
}
}
}
System.out.println("===> 通用响应参数");
System.out.println("Msg :" + map.get("Msg").toString());
}
}
1、存储过程参数 UserID 由 Map 传入
2、参数类型为 Out 的不需要显示声明,在执行完存储过程后,可直接从 Map 中获取返回值
使用 SQL SERVER
SP
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE MyBatisTestSP
@UID varchar(50),@Res varchar(50) OUT,@Msg varchar(50) OUT
AS
SET NOCOUNT ON;
SELECT * FROM TestUser WHERE UserName = @UID
SELECT * FROM TestRight WHERE UserName = @UID
SELECT @Res = 'OK',@Msg = '=> OK'
GO
POM
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.0</version>
</dependency>
1、新增 sql server 依赖
yml
spring:
datasource:
url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=TestDB
username: root
password: root
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
mybatis:
mapper-locations: classpath:mapper/*.xml
XML
<select id="sptest" resultType="java.util.List" resultMap="Map1,Map2" parameterType="Map" statementType="CALLABLE" >
{CALL MyBatisTestSP(#{UID,mode=IN,jdbcType=VARCHAR},#{Res,mode=OUT,jdbcType=VARCHAR},#{Msg,mode=OUT,jdbcType=VARCHAR})}
</select>