在开始阅读本篇前,建议先看前两篇:
MyBatis 示例之存储过程(一)
http://blog.csdn.net/isea533/article/details/76358365
MyBatis 示例之存储过程(二)
http://blog.csdn.net/isea533/article/details/77148552
本示例是《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 createTime = NOW();
# 插入数据
INSERT INTO sys_user(user_name, user_password, user_email, user_info, head_img, create_time)
VALUES (userName, userPassword, userEmail, userInfo, headImg, createTime);
# 获取自增主键
SELECT LAST_INSERT_ID() INTO userId;
# 保存用户和角色关系数据
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 user_id = userId;
DELETE FROM sys_user where id = userId;
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 deleteUserById(Long id);
第一个方法有两个参数,所以使用 @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 {
sqlSession.close();
}
}
这个测试同时进行了插入和删除操作,由于执行的存储过程,通过 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示例 专栏。