MyBatis 08-存储过程
http://www.broadview.com.cn/book/3643
https://github.com/mybatis-book/book
根据用户 id 查询用户其他信息
# 根据用户 id 查询用户其他信息
# 方法看着很奇葩,但是展示了多个输出参数
DROP PROCEDURE IF EXISTS `select_user_by_id`;
DELIMITER ;;
CREATE PROCEDURE `select_user_by_id`(
IN userId BIGINT,
OUT userName VARCHAR(50),
OUT userPassword VARCHAR(50),
OUT userEmail VARCHAR(50),
OUT userInfo TEXT,
OUT headImg BLOB,
OUT createTime DATETIME)
BEGIN
# 根据用户 id 查询其他数据
select user_name,user_password,user_email,user_info,head_img,create_time
INTO userName,userPassword,userEmail,userInfo,headImg,createTime
from sys_user
WHERE id = userId;
END
;;
DELIMITER ;
<select id="selectUserById" statementType="CALLABLE" useCache="false">
{call select_user_by_id(
#{id, mode=IN},
#{userName, mode=OUT, jdbcType=VARCHAR},
#{userPassword, mode=OUT, jdbcType=VARCHAR},
#{userEmail, mode=OUT, jdbcType=VARCHAR},
#{userInfo, mode=OUT, jdbcType=VARCHAR},
#{headImg, mode=OUT, jdbcType=BLOB, javaType=_byte[]},
#{createTime, mode=OUT, jdbcType=TIMESTAMP}
)}
</select>
在调用存储过程的方法中,需要把 statementType 设置为 CALLABLE,在使用 select 标签调用存储过程时,由于存储过程不支持二级缓存,因此避免出错将 useCache 设置为 false。
在存储过程中使用参数时,除了写上必要的属性名,还必须指定参数的 mode,可选值 IN(入参),OUT(出参),INOUT(输入输出)。OUT 模式必须指定 jdbcType。在使用 Oracle 时,如果入参存在 null 的情况,那么入参也必须指定 jdbcType。
void selectUserById(SysUser user);
这个存储过程没有返回值(不要和出参混淆)。
使用出参方式时,使用 JavaBean 对象接收出参时,必须保证所有出参在 JavaBean 中都有对应的属性存在,否则会抛出类似 “Could not set property 'xxx'” 这样的错误。使用 Map 类型接收出参时不需要保证所有出参都有对应的属性。
简单的根据用户名和分页参数进行查询,返回总数和分页数据
# 简单的根据用户名和分页参数进行查询,返回总数和分页数据
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 ;
<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>
select 标签设置了 resultMap,因为该方法通过 total 出参得到了查询的总数,通过存储过程返回了最后的结果集,所以需要设置返回值信息。
/**
* 使用存储过程分页查询
*
* @param userName
* @param pageNum
* @param pageSize
* @param total
* @return
*/
List<SysUser> selectUserPage(Map<String, Object> params);
@Test
public void testSelectUserPage(){
// 获取 sqlSession
SqlSession sqlSession = getSqlSession();
try {
// 获取 UserMapper 接口
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); // 也可以使用 JavaBean
Long total = (Long) params.get("total");
System.out.println("总数:" + total);
for(SysUser user : userList){
System.out.println("用户名:" + user.getUserName());
}
} finally {
// 不要忘记关闭 sqlSession
sqlSession.close();
}
}
添加删除用户
# 保存用户信息和角色关联信息
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 ;
<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>
/**
* 保存用户信息和角色关联信息
*/
int insertUserAndRoles(@Param("user")SysUser user, @Param("roleIds")String roleIds);
/**
* 根据用户 id 删除用户和用户的角色信息
*/
int deleteUserById(Long id);
在 Oracle 中使用游标参数的存储过程
create or replace procedure SELECT_COUNTRIES(
ref_cur1 out sys_refcursor,
ref_cur2 out sys_refcursor) is
begin
open ref_cur1 for select * from country where id < 3;
open ref_cur2 for select * from country where id >= 3;
end SELECT_COUNTRIES;
这个存储过程只有两个游标类型的出参,游标对应的值就是两个简单的 SQL。
<select id="selectCountries" statementType="CALLABLE" useCache="false">
{call SELECT_COUNTRIES(
#{list1, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=BaseResultMap},
#{list2, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=BaseResultMap}
)}
</select>
使用游标类型时,注意设置 jdbcType=CURSOR
, javaType=ResultSet
/**
* 执行 Oracle 中的存储过程
*/
Object selectCountries(Map<String, Object> params);
@Test
public void testMapperWithStartPage3() {
SqlSession sqlSession = getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
// 获取第1页,10条内容,默认查询总数count
Map<String, Object> params = new HashMap<String, Object>();
countryMapper.selectCountries(params);
List<Country> list1 = (List<Country>) params.get("list1");
List<Country> list2 = (List<Country>) params.get("list2");
Assert.assertNotNull(list1);
Assert.assertNotNull(list2);
} finally {
sqlSession.close();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:MyBatis 08-存储过程
文章字数:1.3k
本文作者:Bin
发布时间:2019-12-01, 13:54:52
最后更新:2019-12-01, 14:31:58
原始链接:http://coolview.github.io/2019/12/01/MyBatis/MyBatis%2008-%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。