在开始阅读本篇前,建议先看前两篇:

MyBatis 示例之存储过程(一)

MyBatis 示例之存储过程(二)

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

这一节看看最后两种常见的用法。

基本准备

参考 ​​MyBatis 示例之存储过程(一)​​ 中的内容。

建存储过程

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

# 第三个存储过程
# 保存用户信息和角色关联信息
DROP PROCEDURE IF EXISTS `insert_user_and_roles`;
DELIMITER ;;
CREATE PROCEDURE `insert_user_and_roles`(
OUT userId BIGINT,
IN userName VARCHAR(50),
IN userPassword VARCHAR(50),
IN userEmail VARCHAR(50),
IN userInfo TEXT,
IN headImg BLOB,
OUT createTime DATETIME,
IN roleIds VARCHAR(200)
)

BEGIN
# 设置当前时间
SET
# 插入数据
INSERT INTO sys_user(user_name, user_password, user_email, user_info, head_img, create_time)
VALUES
# 获取自增主键
SELECT LAST_INSERT_ID() INTO
# 保存用户和角色关系数据
SET roleIds = CONCAT(',',roleIds,',');
INSERT INTO sys_user_role(user_id, role_id)
select userId, id from sys_role
where INSTR(roleIds, CONCAT(',',id,',')) > 0;
END;
DELIMITER ;

# 第四个存储过程
# 删除用户信息和角色关联信息
DROP PROCEDURE IF EXISTS `delete_user_by_id`;
DELIMITER ;;
CREATE PROCEDURE `delete_user_by_id`(IN userId BIGINT)
BEGIN
DELETE FROM sys_user_role where
DELETE FROM sys_user where
END;
DELIMITER ;

第一个存储过程在添加用户的同时,还给用户添加了多个角色。

第二个存储过程在删除用户的时候,还删除了关联的角色(如果还有其他用户信息,可以一并删除)。

创建XML方法

<insert id="insertUserAndRoles" statementType="CALLABLE">
{call insert_user_and_roles(
#{user.id, mode=OUT, jdbcType=BIGINT},
#{user.userName, mode=IN},
#{user.userPassword, mode=IN},
#{user.userEmail, mode=IN},
#{user.userInfo, mode=IN},
#{user.headImg, mode=IN, jdbcType=BLOB},
#{user.createTime, mode=OUT, jdbcType=TIMESTAMP},
#{roleIds, mode=IN}
)}
</insert>

<delete id="deleteUserById" statementType="CALLABLE">
{call delete_user_by_id(#{id, mode=IN})}
</delete>

这里要注意的是我们分别使用了 ​​insert​​​ 和 ​​delete​​​ 标签,同样设置 ​​statementType​​​ 属性为 ​​CALLABLE​​。

第一个存储过程在保存用户信息后,还会返回用户的 id 和 创建时间,使用用户 id 还可以继续对新增的用户进行一些其他的操作。 第二个存储过程就只有一个用户 id 的入参。

创建接口

创建两个方法对应的接口方法

/**
* 保存用户信息和角色关联信息
*
* @param user
* @param roleIds
* @return
int insertUserAndRoles(@Param("user")SysUser user, @Param("roleIds")String roleIds);

/**
* 根据用户 id 删除用户和用户的角色信息
*
* @param id
* @return
int

第一个方法有两个参数,所以使用 ​​@Param​​​ 注解指定参数名,注意和 xml 中的属性名结合起来看。在 ​​insertUserAndRoles​​​ 方法中,​​SysUser​​​ 存储了用户了基本信息,​​roleIds​​​ 参数存储了要给该用户的角色 id 字符串,该值如 ​​"1,2,3"​​,使用逗号隔开多个 id。

编写测试

针对两个方法编写测试。

@Test
public void testInsertAndDelete(){
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
SysUser user = new SysUser();
user.setUserName("test1");
user.setUserPassword("123456");
user.setUserEmail("test@mybatis.tk");
user.setUserInfo("test info");
user.setHeadImg(new byte[]{1,2,3});
//插入用户信息和角色关联信息
userMapper.insertUserAndRoles(user, "1,2");
Assert.assertNotNull(user.getId());
Assert.assertNotNull(user.getCreateTime());
//可以执行下面的 commit 后查看数据库中的数据
//sqlSession.commit();
//测试删除刚刚插入的数据
userMapper.deleteUserById(user.getId());
} finally

这个测试同时进行了插入和删除操作,由于执行的存储过程,通过 SQL 日志看不到具体的操作,大家在测试的时候,可以将 ​​deleteUserById​​ 方法单独执行,由于 sqlSession 没有开启自动提交,需要在这里手动 commit。

上述测试输入的日志如下:

DEBUG [main] - ==>  Preparing: {call insert_user_and_roles( ?, ?, ?, ?, ?, ?, ?, ? )} 
DEBUG [main] - ==> Parameters: test1(String), 123456(String), test@mybatis.tk(String), test info(String), java.io.ByteArrayInputStream@2473b9ce(ByteArrayInputStream), 1,2(String)
DEBUG [main] - <== Updates: 2
DEBUG [main] - ==> Preparing: {call delete_user_by_id(?)}
DEBUG [main] - ==> Parameters: 1037(Long)
DEBUG [main] - <== Updates: 1

在我们的 ​​insertUserAndRoles​​ 存储过程中,我们通过出参实现了主键和日期的回写,然后通过返回的主键删除了对应的全部数据。

总结

存储过程常见的用法就是这几类情况,大家可以在使用存储过程时参考文中的代码进行实现。

想要了解更多 MyBatis 用法细节,可以选择购买 ​​《MyBatis 从入门到精通》​​​,或者关注我的 ​​Mybatis示例​​ 专栏。