MyBatis 示例之存储过程(一)

本示例是《MyBatis 从入门到精通》书中第一个存储过程的例子,有关本示例的基础环境,可以从 http://mybatis.tk 或者 https://github.com/mybatis-book/book 获取,示例源码在 simple-all 中。

存储过程在数据库中比较常见,虽然大多数存储过程比较复杂,但是使用 MyBatis 调用时,用法都一样,因此我们这一节使用一个简单的存储过程来了解 MyBatis 中存储过程的使用方法。

基本准备

存储过程涉及表 sys_user,建表语句如下。

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `user_password` varchar(50) DEFAULT NULL COMMENT '密码',
  `user_email` varchar(50) DEFAULT 'test@mybatis.tk' COMMENT '邮箱',
  `user_info` text COMMENT '简介',
  `head_img` blob COMMENT '头像',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1035 DEFAULT CHARSET=utf8 COMMENT='用户表';
准备测试数据如下。

INSERT INTO `sys_user` VALUES ('1', 'admin', '123456', 'admin@mybatis.tk', '管理员用户', 0x1231231230, '2016-06-07 01:11:12');
INSERT INTO `sys_user` VALUES ('1001', 'test', '123456', 'test@mybatis.tk', '测试用户', 0x1231231230, '2016-06-07 00:00:00');
1
2
对应实体类SysUser如下:

/**
 * 用户表
 */
public class SysUser implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 用户ID
     */
    private Long id;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String userPassword;
    /**
     * 邮箱
     */
    private String userEmail;
    /**
     * 简介
     */
    private String userInfo;
    /**
     * 头像
     */
    private byte[] headImg;
    /**
     * 创建时间
     */
    private Date createTime;
    //省略 getter 和 setter
}
建存储过程

我们先创建如下的存储过程。

# 第一个存储过程
# 根据用户 id 查询用户其他信息
# 方法看着很奇葩,但是展示了多个输出参数
DROP PROCEDURE IF EXISTS `select_user_by_id`;
DELIMITER ;;
CREATE PROCEDURE `select_user_by_id`(
IN userId BIGINT,
OUT userName VARCHAR(50),
OUT userPassword VARCHAR(50),
OUT userEmail VARCHAR(50),
OUT userInfo TEXT,
OUT headImg BLOB,
OUT createTime DATETIME)
BEGIN
# 根据用户 id 查询其他数据
select user_name,user_password,user_email,user_info,head_img,create_time
INTO userName,userPassword,userEmail,userInfo,headImg,createTime 
from sys_user
WHERE id = userId;
END
;;
DELIMITER ;
创建XML方法

<select id="selectUserById" statementType="CALLABLE" useCache="false">
    {call select_user_by_id(
        #{id, mode=IN}, 
        #{userName, mode=OUT, jdbcType=VARCHAR},
        #{userPassword, mode=OUT, jdbcType=VARCHAR},
        #{userEmail, mode=OUT, jdbcType=VARCHAR},
        #{userInfo, mode=OUT, jdbcType=VARCHAR},
        #{headImg, mode=OUT, jdbcType=BLOB, javaType=_byte[]},
        #{createTime, mode=OUT, jdbcType=TIMESTAMP}
    )}
</select>
在调用存储过程的方法中,我们需要把 statementType 设置为 CALLABLE,在使用 select 元素中调用存储过程时,由于存储过程方式不支持 MyBatis 的二级缓存(后面章节会介绍),为了避免缓存配置导致出错,我们直接将 select 元素的 useCache 属性设置为 false。

在存储过程中使用参数时,除了写上必要的属性名外,还必须指定参数的 mode(模式),可选值为 IN、OUT、INOUT 三种,入参使用 IN,出参使用 OUT,输入输出参数使用 INOUT。从上面代码可以轻易看出 IN 和 OUT 的两种模式的区别,那就是 OUT 模式的参数,必须指定 jdbcType。这是因为在 IN 模式下,MyBatis 提供了默认的 jdbcType,在 OUT 模式下没有提供,因此必须指定 jdbcType,另外在使用 Oracle 数据库时,如果入参存在 null 的情况,那么也必须指定 jdbcType。

除了上面提到的这几点外,headImg 还特别设置了 javaType。在 MyBatis 映射的 Java 类中我们都不推荐使用基本类型,但是数据库 BLOB 类型对应的 Java 类型我们通常都是写成 byte[] 字节数组,因为 byte[] 数组不会有默认值的问题,所以不会影响我们一般的使用。但是在不指定 javaType 的情况下,MyBatis 默认使用 Byte 类型。由于我们使用的 byte 是基本类型,所以设置 javaType 的时候,基本类型要使用带下划线方式的类型,在这里就是 byte[],_byte 对应的是基本类型,byte 对应的是 Byte 类型,在使用 javaType 时一定要注意。

创建接口

/**
 * 使用存储过程查询用户信息
 * 
 * @param user
 * @return
 */
void selectUserById(SysUser user);
1
2
3
4
5
6
7
因为我们这个存储过程没有返回值(不要和出参混淆),所以我们返回值类型使用 void,如果你把返回值设置为 SysUser 或 List<SysUser> 也不会报错,但是任何时候返回值都是 null。

编写测试

@Test
public void testSelectUserById(){
    SqlSession sqlSession = //获取SqlSession的方法
    try {
        //这个例子的XML和接口都定义在UserMapper中
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        SysUser user = new SysUser();
        user.setId(1L);
        userMapper.selectUserById(user);
        Assert.assertNotNull(user.getUserName());
        System.out.println("用户名:" + user.getUserName());
    } finally {
        sqlSession.close();
    }
}

执行测试,输出如下日志:

DEBUG [main] - ==>  Preparing: {call select_user_by_id( ?, ?, ?, ?, ?, ?, ? )} 
DEBUG [main] - ==> Parameters: 1(Long)
用户名:admin
使用出参方式的时候,通常情况下我们会使用对象中的属性接收出参的值,或者使用 Map 类型方法入参接收返回值。这两种情况下有很大的区别。当我们使用 POJO 对象接收出参时,我们必须保证所有出参在 POJO 中都有对应的属性存在,否则就会抛出类似 “Could not set property 'xxx'”的错误,这是由于 POJO 对象中不存在出参对应的 setter 方法导致的。使用 Map 类型时就不需要必须存在该属性,当 Map 接收了存储过程的出参时,可以通过 Map 对象的 get("属性名") 方法获取出参的值。

错误提示

除了上面提到的错误外,当你在执行存储过程时,还可能会遇到下面的错误:

Parameter number x is not an OUT parameter

这个错误可能的原因是因为你调用的存储过程不存在,或者 MyBatis 中写的出参和数据库存储过程的出参对应不上而导致的。
--------------------- 
作者:isea533 
来源:CSDN 
原文:https://blog.csdn.net/isea533/article/details/76358365 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MyBatis是一种持久层框架,可以用来调用MySQL存储过程。使用MyBatis调用MySQL存储过程的步骤如下: 1.在MySQL数据库中创建存储过程。 2.在MyBatis的配置文件中配置存储过程的调用语句。 3.在Java代码中使用MyBatis的API调用存储过程示例: 1. 创建存储过程 ``` DELIMITER $$ CREATE PROCEDURE get_student_by_id (IN p_student_id INT) BEGIN SELECT * FROM student WHERE id = p_student_id; END $$ DELIMITER ; ``` 2. 配置Mybatis ``` <select id="getStudentById" parameterType="int" statementType="CALLABLE"> {call get_student_by_id(#{studentId,jdbcType=INTEGER,mode=IN})} </select> ``` 3. 在Java代码中调用存储过程 ``` SqlSession sqlSession = sqlSessionFactory.openSession(); try { StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student student = studentMapper.getStudentById(1); ... } finally { sqlSession.close(); } ``` 希望这对你有帮助。 ### 回答2: MyBatis是一个非常流行的Java ORM框架,其优点在于它可以自定义SQL语句,更加精准地控制SQL操作。在项目开发中,有时需要调用MySQL存储过程。下面将详细介绍如何使用MyBatis调用存储过程。 首先,在MyBatis的Mapper.xml文件中定义存储过程调用。在这个文件中,你需要: 1. 定义一个`<select>`语句,用于调用存储过程并获取数据。 2. 设置存储过程的名称。 3. 传递存储过程的参数以及它们的数据类型。 下面是示例代码: ```xml <select id="callProcedure" statementType="CALLABLE" parameterType="hashmap" resultType="hashmap"> CALL procedure_name(#{param2,mode=IN,jdbcType=VARCHAR},#{param3,mode=IN,jdbcType=VARCHAR},#{results,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=resultMap}) </select> ``` 其中,statementType属性设置为`CALLABLE`,表示这是一个调用存储过程的语句。parameterType属性表示参数类型。resultType属性表示存储过程返回的结果集类型。 上述代码中,`#{param2}`和`#{param3}`分别表示存储过程的两个输入参数。`#{results}`表示存储过程的输出参数,也就是结果集。 在这个示例中,我们默认结果集的类型为`ResultSet`,并将其映射到了另一个resultMap中。而`#{results, mode=OUT, jdbcType=CURSOR}`这个语句则告诉MyBatis将结果集的游标传递给数据库驱动程序。 这样,你就可以使用MyBatis调用MySQL存储过程了。在调用存储过程之前,你需要将存储过程的定义写入数据库中。这可以通过使用MySQL的命令行或者直接使用MySQL Workbench添加存储过程来实现。 总结来说,要使用MyBatis调用MySQL存储过程,你需要定义用于调用存储过程的语句,并在其中设置存储过程的名称、参数和结果集类型等信息。除此之外,你还需要将存储过程定义写入数据库中,才能实现MyBatis和MySQL存储过程的联动。 ### 回答3: MyBatis 是一款主流的 ORM 框架,可以提供持久层的数据访问和对象映射的支持。在实际开发中,经常需要调用存储过程来完成一些业务操作,本文将介绍如何使用 MyBatis 调用 MySQL 存储过程。 首先,在 MySQL 中创建一个存储过程。例如,下面创建了一个存储过程,用来查询所有用户的信息: ``` DELIMITER // CREATE PROCEDURE get_all_users() BEGIN SELECT * FROM users; END // DELIMITER ; ``` 接下来,在 MyBatis 中定义一个接口,用来调用该存储过程。例如: ``` public interface UserMapper { @Select("CALL get_all_users()") @Results({ @Result(property = "id", column = "id"), @Result(property = "name", column = "name"), @Result(property = "gender", column = "gender"), @Result(property = "age", column = "age"), @Result(property = "email", column = "email"), @Result(property = "phone", column = "phone"), @Result(property = "address", column = "address"), }) List<User> getAllUsers(); } ``` MyBatis 提供了 `@Select` 注解来执行 SQL 语句,包括调用存储过程。在查询所有用户的操作中,我们使用 `CALL` 关键字来调用 `get_all_users` 存储过程。 由于存储过程的返回结果不是一个表,而是一组输出参数,我们需要通过 `@Result` 注解来映射存储过程的输出参数到 Java 对象的属性上。在上述代码中,我们映射了 `id`、`name`、`gender`、`age`、`email`、`phone` 和 `address` 这七个字段。 最后,在我们的代码中调用该接口即可: ``` SqlSessionFactory sessionFactory = ...; try (SqlSession session = sessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); List<User> users = mapper.getAllUsers(); // ... } ``` 总的来说,使用 MyBatis 调用 MySQL 存储过程非常简单。只需要定义接口,并使用 `@Select` 和 `@Result` 注解来执行存储过程和映射输出参数,即可完成该操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值