MyBatis中使用存储过程

MyBatis中使用存储过程

在上一篇文章中,主要介绍了MySQL中存储过程的使用,对存储过程还不了解的小伙伴 快去戳我的上一片文章吧MySQL存储过程。在开发过程中,我们大部分都是通过MyBatis来操作数据库,因此在这篇文章中将主要介绍在MyBatis中如何使用存储过程。

在MyBatis中使用存储过程,主要涉及的两个点就是,对于调用存储过程时所需要的入参,我们应该如何传进去?对于执行存储过程后的输出参数我们应该如何得到。

调用普通的存储过程

数据准备

  • 准备两个个数据库表user和accounts
CREATE TABLE `user` (  
    `id` int(11NOT NULL AUTO_INCREMENT, 
    `username` varchar(32NOT NULL COMMENT '用户名称', 
    `birthday` datetime DEFAULT NULL COMMENT '生日',   
    `sex` char(1DEFAULT NULL COMMENT '性别',  
    `address` varchar(256DEFAULT NULL COMMENT '地址', 
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=78 DEFAULT CHARSET=utf8
CREATE TABLE `accounts` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `name` char(100NOT NULL,
  `money` float DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
  • 在SqlYog中建一个普通的存储过程,名称为test1
DELIMITER $$

CREATE
    PROCEDURE `students`.`test1`()
    BEGIN
	SELECT * FROM USER;
    END$$

DELIMITER ;
  • 配置MyBatis这里就略过,直接上Dao层写接口方法,并到XML中写调用存储过程的SQL
  1. Dao方法
public interface UserMapper extends BaseMapper<User> {
    //查询User表中的所有信息
    List<User> test1();

}
  1. 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.mp.mapper.UserMapper">
    <!--因为我们查询的结果返回的是多个记录,因此需要使用resultMap来封装-->
    <resultMap id="BaseResultMap" type="com.example.mp.pojo.User">
        <id column="id" property="id"></id>
        <result column="sex" property="sex"></result>
        <result property="birthday" column="birthday"></result>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
    </resultMap>
    <!--调用test1存储过程-->
    <select id="test1" statementType="CALLABLE" resultMap="BaseResultMap"  >
        call test1();
    </select>

</mapper>

🚦❗ 其中statementType的三个可选值:

CALLABLE:执行存储过程

PREPARED(默认): 预处理、预编译

STATEMENT: 直接操作sql语句,不进行预处理,${}

⚒同理,如果返回的是多个结果集(例如存储过程查询的是两个表的所有数据,那么返回的就是两个不同的结果集),则对应的配置select标签的resultMap应该配置为如下:

<!--结果集1-->
<resultMap id="BaseResultMap" type="com.example.mp.pojo.User">
    <id column="id" property="id"></id>
    <result column="sex" property="sex"></result>
    <result property="birthday" column="birthday"></result>
    <result property="username" column="username"></result>
    <result property="address" column="address"></result>
</resultMap>
<!--结果集2-->
<resultMap id="resultMap2" type="com.example.mp.pojo.Accounts">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="money" property="money"></result>
</resultMap>

<select id="test1" statementType="CALLABLE" resultMap="BaseResultMap,resultMap2" >
    call test1();
</select>

  • 测试 🚗返回单个结果集:
@Test
void test() {
    List<User> users = userMapper.test1();
    for (User user : users) {
        System.out.println(user.toString());
    }
}
  • 控制台输出:

image.png

🚈返回多个结果集:

  • 对应的Dao接口方法
List<List<?>> test1();
@Test
void test() {
    List<List<?>> lists = userMapper.test1();
    for (List<?> list : lists) {
        for (Object o : list) {
            System.out.println(o);
        }
    }
}
  • 控制台输出

image.png

调用带入参的存储过程

  • 创建一个In模型的存储过程,其中存储过程使用的功能为插入新数据到accounts表中
DELIMITER $$

USE `students`$$

DROP PROCEDURE IF EXISTS `test2`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `test2`(IN id INT,IN NAME VARCHAR(20),IN money DOUBLE)
BEGIN
	INSERT INTO accounts (id,NAME,money) VALUES(id,NAME,money);
    END$$

DELIMITER ;
  • Dao接口
void test2(Accounts accounts);
  • XML映射文件
<insert id="test2" statementType="CALLABLE" parameterType="com.example.mp.pojo.Accounts">
    call test2(
    #{id,mode=IN,jdbcType=INTEGER},
    #{name,mode=IN,jdbcType=VARCHAR},
    #{money,mode=IN,jdbcType=DOUBLE}
    )
</insert>
  • 测试
@Test
void test() {
   
    Accounts ac = new Accounts(5, "不喝奶茶的Programmer", 1000.0);
    userMapper.test2(ac);
}
  • 控制台输出

image.png

调用有出参的存储过程

  • 创建一个OUT模型的存储过程,其中存储过程使用的功能为获取accounts表中的记录数
DELIMITER $$

USE `students`$$

DROP PROCEDURE IF EXISTS `test3`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `test3`(OUT num INTEGER)
BEGIN
	SELECT COUNT(*) INTO num FROM accounts;
END$$

DELIMITER ;
  • Dao方法
void test3(HashMap<String, Integer> map);
  • XML映射文件
<!--封装输出参数-->
<parameterMap id="pmap" type="java.util.Map">
    <parameter property="num" mode="OUT" jdbcType="INTEGER"></parameter>
</parameterMap>

<select id="test3" parameterMap="pmap" statementType="CALLABLE">
    call test3(?);
</select>
  • 测试
@Test
void test() {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("num",-1);
    userMapper.test3(map);
    System.out.println(map.get("num"));
}
  • 控制台输出结果

image.png

调用既有出参又有入参的存储过程

  • 创建一个OUT模型的存储过程,其中存储过程使用的功能为新增一条记录到accounts表中,并查询表中的记录数
DELIMITER $$

USE `students`$$

DROP PROCEDURE IF EXISTS `test4`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `test4`(IN id INTEGER,IN NAME VARCHAR(20),IN money INTEGER, OUT num INTEGER)
BEGIN
	INSERT INTO accounts (id,NAME,money) VALUES(id,NAME,money);
	SELECT COUNT(*) INTO num FROM accounts;
    END$$

DELIMITER ;
  • Dao方法
void test4(HashMap<String, Object> map);
  • XML映射文件
<parameterMap id="pmap2" type="java.util.Map">
    <parameter property="id" mode="IN" jdbcType="INTEGER"></parameter>
    <parameter property="name" mode="IN" jdbcType="VARCHAR"></parameter>
    <parameter property="money" mode="IN" jdbcType="INTEGER"></parameter>
    <parameter property="num" mode="OUT" jdbcType="INTEGER"></parameter>
</parameterMap>

<insert id="test4" parameterMap="pmap2" statementType="CALLABLE">
    call test4(?,?,?,?)
</insert>
  • 测试
@Test
    void test() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("id",6);
        map.put("name","demo");
        map.put("money",120);
        map.put("num",-1);
        userMapper.test4(map);
        System.out.println(map.get("num"));
    }
}
  • 控制台输出

image.png

🏁以上就是对MyBatis中使用存储过程简单介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍

默认标题_动态分割线_2021-07-15-0.gif