MyBatis 示例之存储过程(三)

版权声明:版权归博主所有,转载请带上本文链接!联系方式:abel533@gmail.com https://blog.csdn.net/isea533/article/details/77592456

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

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>

这里要注意的是我们分别使用了 insertdelete 标签,同样设置 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示例 专栏。

阅读更多

扫码向博主提问

isea533

博客专家

MyBatis相关答疑
  • 擅长领域:
  • MyBatis
  • Spring Boo
  • Spring
去开通我的Chat快问
换一批

没有更多推荐了,返回首页