在开始阅读本篇前,建议先看前一篇:
MyBatis 示例之存储过程(一)
http://blog.csdn.net/isea533/article/details/76358365
本示例是《MyBatis 从入门到精通》书中第二个存储过程的例子,有关本示例的基础环境,可以从 http://mybatis.tk 或者 https://github.com/mybatis-book/book 获取,示例源码在 simple-all 中。
存储过程在数据库中比较常见,虽然大多数存储过程比较复杂,但是使用 MyBatis 调用时,用法都一样,因此我们这一节使用一个简单的存储过程来了解 MyBatis 中存储过程的使用方法。
基本准备
参考 MyBatis 示例之存储过程(一) 中的内容。
建存储过程
我们先创建如下的存储过程。
# 第二个存储过程
# 简单的根据用户名和分页参数进行查询,返回总数和分页数据
DROP PROCEDURE IF EXISTS `select_user_page`;
DELIMITER ;;
CREATE PROCEDURE `select_user_page`(
IN userName VARCHAR(50),
IN _offset BIGINT,
IN _limit BIGINT,
OUT total BIGINT)
BEGIN
# 查询数据总数
select count(*) INTO total
from sys_user
where user_name like concat('%', userName, '%');
# 分页查询数据
select *
from sys_user
where user_name like concat('%', userName, '%')
limit _offset, _limit;
END
;;
DELIMITER ;
创建XML方法
<select id="selectUserPage" statementType="CALLABLE" useCache="false" resultMap="userMap">
{call select_user_page(
#{userName, mode=IN},
#{offset, mode=IN},
#{limit, mode=IN},
#{total, mode=OUT, jdbcType=BIGINT}
)}
</select>
第二个存储过程除了出参 total 外,还有返回值,所以 select
标签设置了返回值类型 resultMap
。userMap
如下:
<resultMap id="userMap" type="tk.mybatis.simple.model.SysUser">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<result property="userEmail" column="user_email"/>
<result property="userInfo" column="user_info"/>
<result property="headImg" column="head_img" jdbcType="BLOB"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
创建接口
/**
* 使用存储过程分页查询
*
* @param userName
* @param pageNum
* @param pageSize
* @param total
* @return
*/
List<SysUser> selectUserPage(Map<String, Object> params);
由于我们需要多个入参和一个出参,入参中除了 userName 属性在 SysUser 中外,其他 3 个参数都和 SysUser 无关,如果为了使用 SysUser 增加 3 个属性也可以。这里为了方法的多样化,也为了印证上一个方法中关于 Map 的用法,我们这里使用了 Map 类型作为参数。
编写测试
@Test
public void testSelectUserPage(){
SqlSession sqlSession = getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> params = new HashMap<String, Object>();
params.put("userName", "ad");
params.put("offset", 0);
params.put("limit", 10);
List<SysUser> userList = userMapper.selectUserPage(params);
Long total = (Long) params.get("total");
System.out.println("总数:" + total);
for(SysUser user : userList){
System.out.println("用户名:" + user.getUserName());
}
} finally {
sqlSession.close();
}
}
在我们测试代码的 Map 参数中不存在 total,在我们执行了存储过程方法后,通过 get 方法得到了 total 的值。上面测试代码的输出日志如下:
DEBUG [main] - ==> Preparing: {call select_user_page( ?, ?, ?, ? )}
DEBUG [main] - ==> Parameters: ad(String), 0(Integer), 10(Integer)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, <<BLOB>>, <<BLOB>>, 2016-06-07 01:11:12.0
DEBUG [main] - <== Total: 1
DEBUG [main] - <== Updates: 0
总数:1
用户名:admin
为了更有效的测试这个分页查询的存储过程,你可以往数据库中增加大量数据进行测试。