10.3 MyBatis调用存储过程 SQL
语句在执行的时候需要先编译,然后执行。数据库的存储过程(Procedure
)是组为了完成特定功能的SQL
语句,编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用存储过程。 使用存储过程可提高数据库执行速度,并且存储过程可以重复使用,从而减少数据库开发人员的工作量。 下面重点介绍如何使用MyBatis
调用存储过程。
10.3.1插入数据 测试数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 DROP TABLE IF EXISTS `tb_user` ;CREATE TABLE `tb_user` ( `id` int (11 ) NOT NULL AUTO_INCREMENT, `name` varchar (18 ) DEFAULT NULL , `sex` char (2 ) DEFAULT NULL , `age` int (11 ) DEFAULT NULL , PRIMARY KEY (`id` ) ) ENGINE =InnoDB DEFAULT CHARSET =utf8mb4; INSERT INTO `tb_user` VALUES ('1' , '小明' , '男' , '21' );INSERT INTO `tb_user` VALUES ('2' , '小王' , '男' , '22' );INSERT INTO `tb_user` VALUES ('3' , '小丽' , '女' , '18' );INSERT INTO `tb_user` VALUES ('4' , '小芳' , '女' , '18' );
创建存储过程 在之前创建的mybatis
数据库中创建一个插入tb_user
表数据的存储过程,SQL
脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 drop procedure if exists insert_user;DELIMITER $$ CREATE PROCEDURE insert_user ( OUT v_id int , in v_name varchar (18 ), in v_sex varchar (19 ), in v_age int ) BEGIN INSERT INTO tb_user (name ,sex,age) VALUES (v_name,v_sex,v_age); SET v_id=LAST_INSERT_ID (); END $$ DELIMITER ;
存储过程代码详解 以上存储过程代码解释如下:
DELIMITER
是MySQL
解释器,用于规定SQL
语句的结束符,默认情况SQL
语句的结束符是分号(;
).为了录入存储过程中的SQL
语句,我们需要先把默认的结束符(;
)换成其他字符,录入结束后再把结束符换回分号.
在存储过程中使用参数时,除了参数名和参数类型之外,还建议指定参数的mode
(模式),可选值为IN
、OUT
和INOUT
三种。
输入参数使用IN
,
输出参数(返回)使用OUT
,
输入输出参数使用 INOUT
。
LAST_INSERT_ID
是 MySQL
的函数,和AUTO_INCREMENT
属性一起使用,当往带有AUTO_INCREMENT
属性字段的表中新增数据时, LAST_INSERT_ID
函数返回该字段的值。
命令行调用存储过程 调用示例如下:
1 call insert_user(@output ,'小王' ,'男' ,22 );
第一个参数@output
是一个变量,用来接收存储过程的输出. 其三个参数是存储过程的输入.
显示存储过程的输出 select 输出变量名;
即可显示存储过程的输出,如下代码所示:
运行结果如下:
1 2 3 4 5 6 7 8 9 mysql> call insert_user(@output,'小王','男',22 ); Database changed mysql> select @output; +---------+ | @output | +---------+ | 5 | +---------+ 1 row in set
此时tb_user
表中的数据如下:
1 2 3 4 5 6 7 8 9 10 11 mysql> select * from tb_user; +----+------+-----+-----+ | id | name | sex | age | +----+------+-----+-----+ | 1 | 小明 | 男 | 21 | | 2 | 小王 | 男 | 22 | | 3 | 小丽 | 女 | 18 | | 4 | 小芳 | 女 | 18 | | 5 | 小王 | 男 | 22 | +----+------+-----+-----+ 5 rows in set
创建持久化对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package domain;public class User { private Integer id; private String name; private String sex; private Integer age; public User () { super (); } @Override public String toString () { return "User [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + "]" ; } }
编写Mapper.xml映射文件 1 2 3 4 5 6 7 8 9 10 11 <insert id ="inserUser" parameterType ="domain.User" statementType ="CALLABLE" > { call insert_user( #{id,mode=OUT,jdbcType=INTEGER}, #{name,mode=IN}, #{sex,mode=IN}, #{age,mode=IN} ) } </insert >
insert
标签调用名为”insert_user
“的存储过程完成一个插入数据的操作。调用存储过程时,需要把statementType
属性的值设置为”CALLABLE
“。 “call
“是用来调用存储过程的关键字,需要注意的是,OUT
模式的参数必须指定jdbcType
,这是因为在IN
模式下,MyBatis
提供了默认的jdbcType
,而在OUT
模式下没有提供。 注意id
列的参数jdbcType
不要写成javaType
.
编写mapper接口 1 2 3 4 5 package mapper;import domain.User;public interface UserMapper { void inserUser (User user) ; }
编写测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package test;import domain.User;import org.apache.ibatis.session.SqlSession;import fractory.SqlSessionFratoryTools;import mapper.UserMapper;public class inserTest { public static void main (String[] args) { SqlSession sqlSession = null ; sqlSession = SqlSessionFratoryTools.getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setAge(23 ); user.setName("小李" ); user.setSex("男" ); userMapper.inserUser(user); sqlSession.commit(); System.out.println("自动生成的Id:" + user.getId()); } catch (Exception e) { sqlSession.rollback(); e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } }
运行效果 此时tb_user
表中的数据如下:
1 2 3 4 5 6 7 8 9 10 11 mysql> select * from tb_user; +----+------+-----+-----+ | id | name | sex | age | +----+------+-----+-----+ | 1 | 小明 | 男 | 21 | | 2 | 小王 | 男 | 22 | | 3 | 小丽 | 女 | 18 | | 4 | 小芳 | 女 | 18 | | 5 | 小王 | 男 | 22 | +----+------+-----+-----+ 5 rows in set
运行测试类,inserUser()
方法将会插入一个用户记录到数据库表中,并输出自动生成的id
值。控制台显示如下:
1 2 3 4 DEBUG [main] ==> Preparing: { call insert_user( ?, ?, ?, ? ) } DEBUG [main] ==> Parameters: 小李(String), 男(String), 23 (Integer) DEBUG [main] <== Updates: 1 自动生成的Id:6
可以看到,MyBatis
调用了名为”insert_user
“的存储过程,并且传入了4
个参数.其中第一个参数id
用来接收存储过程的输出.所以尽管我们没有给user
对象的id
属性复制,但是存储过程插入成功后,id
属性的值变成了6
. 查询数据库,可以看到tb_user
表中插入了一条新的记录,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 mysql> select * from tb_user; +----+------+-----+-----+ | id | name | sex | age | +----+------+-----+-----+ | 1 | 小明 | 男 | 21 | | 2 | 小王 | 男 | 22 | | 3 | 小丽 | 女 | 18 | | 4 | 小芳 | 女 | 18 | | 5 | 小王 | 男 | 22 | | 6 | 小李 | 男 | 23 | +----+------+-----+-----+ 6 rows in set
原文链接: 10.3 MyBatis调用存储过程 10.3.1插入数据