Mybatis调用存储过程的案例
作者:绿野仙踪max
推荐阅读:
Mybatis如何调用存储过程
一、前置工作
1.首先,我们需要创建一个学生表,以下是学生表的建表语句:
create table student
(
    id   int         not null
        primary key,
    name varchar(10) not null,
    sex  varchar(10) not null,
    age  int         not null
);2.接下来,我们创建一个与学生表对应的实体类,用于映射数据库中的记录。以下是一个简单的学生实体类的示例:
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {
    int id;
    String name;
    String sex;
    int age;
}3.最后,我们将定义存储过程来查询符合指定性别的学生信息和总条数。存储过程代码如下:
CREATE PROCEDURE getStudentBySex(IN p_sex VARCHAR(255),OUT p_totalCount INT)
BEGIN
    SELECT COUNT(*) INTO p_totalCount FROM student WHERE sex = p_sex;
    SELECT * FROM student WHERE sex = p_sex;
END;二、基于xml文件调用存储过程
1.首先配置MyBatis的配置文件,以下是配置参数:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql的环境-->
        <environment id="mysql">
            <!--配置事物类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&allowMultiQueries=true&multipleStatements=true"/>
                <property name="username" value="root"/><!--数据库账号-->
                <property name="password" value="013579"/><!--数据库密码-->
            </dataSource>
        </environment>
    </environments>
    <!--映射配置,这样的配置,MyBatis就能够加载StudentDao.xml映射文件,并将其与相应的DAO接口关联起来,使您能够在代码中使用该接口来调用存储过程。-->
    <mappers>
        <mapper resource="dao/StudentDao.xml"/>
    </mappers>
</configuration>2.DAO 层函数定义:
@Mapper
public interface StudentDao {
    List<Student> getStudentForSex(Map<String,Object> param);
}3.配置 XML 文件与 DAO 层函数进行映射,实现调用存储过程,以下是配置内容的示例:
<mapper namespace="dao.StudentDao">
    <select id="getStudentForSex" statementType="CALLABLE" resultType="pojo.Student">
        {call getStudentBySex(#{p_sex, mode=IN, jdbcType=VARCHAR},#{p_totalCount, mode=OUT, jdbcType=INTEGER})}
    </select>
</mapper>- namespace:需要与dao层接口保持一致,才能成功映射,这里设置为"dao.StudentDao"。
 - id:表示映射语句的唯一标识符,要与dao层对应的函数名称一致,这里设置为"getStudentForSex"。
 - statementType:指定语句的类型,这里设置为"CALLABLE",表示调用存储过程。
 - resultType:指定查询结果的返回类型,要与dao层函数返回值的类型保持一致,这里设置为"pojo.Student",表示返回一个Student对象作为结果。
 - #{p_sex, mode=IN, jdbcType=VARCHAR}:这是输入参数p_sex的配置,其中:
 - 1.p_sex:表示输入参数的名称。
 - 2.mode=IN:表示该参数是一个输入参数。
 - 3.jdbcType=VARCHAR:表示输入参数的JDBC类型为VARCHAR。
 - #{p_totalCount, mode=OUT, jdbcType=INTEGER}:这是输出参数p_totalCount的配置,其中:
 - 1.p_totalCount:表示输出参数的名称。
 - 2.mode=OUT:表示该参数是一个输出参数。
 - 3.jdbcType=INTEGER:表示输出参数的JDBC类型为INTEGER。
 
3.测试过程如下:
public class test {
    public static void main(String[] args) throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2、创建 SqlSessionFactoryBuilder 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3、使用构建者模式创建工厂对象 SqlSessionFactory
        SqlSessionFactory factory = builder.build(in);
        //4、使用SqlSessionFactory 生产 SqlSession
        SqlSession session = factory.openSession();
        //5、使用SqlSession 创建 dao接口的代理对象
        StudentDao mapper = session.getMapper(StudentDao.class);
        //6、使用代理对象执行查询所有的方法
        Map<String,Object> param=new HashMap<String, Object>();
        param.put("p_sex","男");
        //7、调用方法
        List<Student> studentList=  mapper.getStudentForSex(param);
        System.out.println("查询的学生结果集: "+studentList);
        //8、输出查询总数
        Object count=param.get("p_totalCount");
        System.out.println("查询的结果总数: "+count);
    }
}4.测试结果如下:

5.过程分析:
到这里大家可能有些疑惑,为什么存储过程中有两个参数getStudentBySex(IN p_sex VARCHAR(255),OUT p_totalCount INT),但是 DAO 层函数getStudentForSex(Map<String,Object> param)确只有一个参数,不应该是一一对应吗?其实不然,在MyBatis中,存储过程的参数和DAO层函数的参数之间并不需要一一对应。这是因为MyBatis提供了一种通过参数的名称来匹配的机制,而不仅仅依赖于参数的位置。
在上述示例中,存储过程 getStudentBySex 定义了两个参数:p_sex 和 p_totalCount。而在DAO层函数 getStudentForSex 中,只有一个参数 param,它是一个 Map<String, Object> 类型的参数。这个参数中的key和value可以与存储过程中的参数名称进行匹配。在实际调用时,可以通过以下方式传递参数:
Map<String,Object> param=new HashMap<String, Object>();
param.put("p_sex","男");
List<Student> studentList=  mapper.getStudentForSex(param);
Object count=param.get("p_totalCount");MyBatis会通过参数名称 “p_sex” 将值 “男” 传递给存储过程的 p_sex 参数。对于输出参数 p_totalCount,MyBatis会自动将存储过程的输出参数(OUT参数)的值放置在Map<String, Object>类型的参数对象中。这是因为MyBatis使用参数名称作为键,参数值作为值,将存储过程的输出结果映射到参数对象中。 在示例中,我们使用Map<String, Object>作为DAO层函数的参数对象。当执行带有输出参数的存储过程时,MyBatis会自动将输出参数的值设置到该Map对象中,以键值对的形式存储。在调用studentDao.getStudentForSex(param)时,MyBatis会执行存储过程并将输出参数的值设置到param对象中。这样,就可以通过访问param对象来获取存储过程执行后的输出参数值。
三、基于注解调用存储过程
- 使用注解调用存储过程比使用 XML 简单一些,因为不需要定义与 DAO 层函数进行映射的 XML 文件,只需要使用两个关键注解即可。以下是实现过程的详细步骤:
 
1.首先配置 MyBatis 的配置文件。以下是配置参数的示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql的环境-->
        <environment id="mysql">
            <!--配置事物类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&allowMultiQueries=true&multipleStatements=true"/>
                <property name="username" value="root"/>
                <property name="password" value="013579"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
    	<!-- StudentDao映射器 -->
    	<mapper class="dao.StudentDao"/>
	</mappers>
</configuration>请注意,与之前的配置不同,这里的 扫描的是接口,而不是 XML 文件。
2.使用注解方式调用存储过程:
@Mapper
public interface StudentDao {
    @Select("call getStudentBySex(#{p_sex,mode=IN,jdbcType=VARCHAR},#{p_totalCount,mode=OUT,jdbcType=INTEGER})")
    @Options(statementType = StatementType.CALLABLE)
    List<Student> getStudentForSex(Map<String,Object> param);
}- @Select: 这是 MyBatis 的注解,用于指定 SQL 查询语句。在这里,我们使用了存储过程的调用语法call,并指定了存储过程名为 getStudentBySex。通过 ${} 语法,我们将参数 p_sex 和 p_totalCount 与方法参数 param 中的对应键值进行绑定。mode=IN 表示参数的传入模式为输入参数,mode=OUT表示参数的传入模式为输出参数。jdbcType=VARCHAR 和 jdbcType=INTEGER 则指定了参数的 JDBC 类型。
 - @Options: 这是 MyBatis 的注解,用于配置选项。在这里,我们使用了 statementType =StatementType.CALLABLE,表示该语句为可调用语句类型。
 - List: 这是方法的返回类型,表示该方法将返回一个 Student 对象的列表。
 
3.测试过程如下:
public class test {
    public static void main(String[] args) throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2、创建 SqlSessionFactoryBuilder 的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3、使用构建者模式创建工厂对象 SqlSessionFactory
        SqlSessionFactory factory = builder.build(in);
        //4、使用SqlSessionFactory 生产 SqlSession
        SqlSession session = factory.openSession();
        //5、使用SqlSession 创建 dao接口的代理对象
        StudentDao mapper = session.getMapper(StudentDao.class);
        //6、使用代理对象执行查询所有的方法
        Map<String,Object> param=new HashMap<String, Object>();
        param.put("p_sex","男");
        //7、调用方法
        List<Student> studentList=  mapper.getStudentForSex(param);
        System.out.println("查询的学生结果集: "+studentList);
        //8、输出查询总数
        Object count=param.get("p_totalCount");
        System.out.println("查询的结果总数: "+count);
    }
}4.测试结果如下:

四、结语
到此这篇关于Mybatis如何调用存储过程的文章就介绍到这了,更多相关mybatis调用存储过程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
