【筆記】Mybatis高階查詢(七)--儲存過程呼叫
阿新 • • 發佈:2018-11-01
以下例子展示Mybatis儲存過程呼叫,與普通查詢基本一樣,只是在配置對映時要加上statementType=“CALLABLE”,由於儲存過程方式不支援Mybatis的二級快取,所以要加上useCache=“false”。
在儲存過程中使用引數時,除了配置屬性名外,還需要指定mode引數,可選值為IN、OUT、INOUT三種,入參用IN,出參用OUT,OUT模式必須指定jdbcType。另外在oracle資料庫時,如果入參存在null的也要指定jdbcType。
使用出參方式時,通常情況下會使用javaBean或Map型別接收。這2種方式有很大區別:
1. 儲存過程select_user_by_id,通過使用者id查詢使用者資訊,無返回值並使用javaBean接收出參
- 在MYSQL中建立儲存過程select_user_by_id
# 根據使用者編號查詢其它資料 DROP PROCEDURE IF EXISTS ‘select_user_by_id’; DELIMITER ;; CREATE PROCEDURE `select_user_by_id`( IN userId BIGINT, OUT userName VARCHAR(60), OUT userPassword VARCHAR(60), OUT userEmail VARCHAR(60), OUT userInfo TEXT, OUT headImg BLOB, OUT createTime DATETIME) BEGIN # 根據使用者編號查詢其它資料 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 ;
- 在SysUserMapper.xml中新增儲存過程呼叫方法selectUserByIdPro
<!-- 儲存過程的select_user_by_id呼叫 ,使用javaBean接收出參--> <select id="selectUserByIdPro" 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>
- 在SysUserMapper介面中新增儲存過程呼叫方法selectUserByIdPro
/**
* 使用儲存過程,根據使用者id查使用者資訊,使用javaBean(SysUser)接收儲存過程出參
* 因為這個儲存過程沒有返回值(不要與出參搞混),所以返回值型別為void,當然設為
* SysUser或List<SysUser>都不會報錯,不過永遠返回null
* @param user
*/
void selectUserByIdPro(SysUser user);
- 在UserMaperTest新增selectUserByIdPro測試方法
@Test
public void testSelectUserByIdPro() {
// 獲取SqlSession
SqlSession sqlSession = openSession();
try {
// 獲取SysUserMapper介面
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
// 查詢條件
SysUser user = new SysUser();
user.setId(1L);
// 呼叫selectUserByIdPro方法
userMapper.selectUserByIdPro(user);
// user不為空
Assert.assertNotNull(user.getUserName());
// 查詢使用者資訊
System.out.println(user);
} finally {
sqlSession.close();
}
}
- select_user_by_id 執行結果(可以看到儲存過程已呼叫並用戶資訊已查出來)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro] - ==> Preparing: {call select_user_by_id ( ?, ?, ?, ?, ?, ?, ? )}
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro] - ==> Parameters: 1(Long)
SysUser [id=1, userName=admin, userPassword=123456, [email protected], createTime=2018-10-01 18:27:36.0, userInfo=管理員, headImg=null]
2. 上一儲存過程select_user_by_id有返回值的寫法
- 在MYSQL中建立儲存過程select_user_by_id_1
CREATE PROCEDURE `select_user_by_id_1`(IN userId BIGINT)
BEGIN
# 根據使用者編號查詢其它資料
SELECT * FROM sys_user WHERE id = userId;
END;
- 在SysUserMapper.xml中新增儲存過程呼叫方法selectUserByIdPro1
<!-- 儲存過程的呼叫 ,有返回值的用法,返回值使用resultMap指定 -->
<select id="selectUserByIdPro1" statementType="CALLABLE" useCache="false" resultMap="userMap">
{call select_user_by_id_1 (#{id, mode=IN})}
</select>
- 在SysUserMapper介面中新增儲存過程呼叫方法selectUserByIdPro1
/**
* 使用儲存過程,根據編號查使用者資訊
* @param id
*/
SysUser selectUserByIdPro1(Long id);
- 在UserMaperTest新增selectUserByIdPro1測試方法
@Test
public void testSelectUserByIdPro1() {
// 獲取SqlSession
SqlSession sqlSession = openSession();
try {
// 獲取SysUserMapper介面
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
// 呼叫selectUserByIdPro1方法
SysUser user = userMapper.selectUserByIdPro1(1L);
// user不為空
Assert.assertNotNull(user.getUserName());
// 查詢使用者資訊
System.out.println(user);
} finally {
sqlSession.close();
}
}
- select_user_by_id_1 執行結果(可以看到儲存過程已呼叫並用戶資訊已查出來)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - ==> Preparing: {call select_user_by_id_1 (?)}
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - ==> Parameters: 1(Long)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - <== Row: 1, admin, 123456, [email protected], <<BLOB>>, <<BLOB>>, 2018-10-01 18:27:36.0
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - <== Total: 1
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserByIdPro1] - <== Updates: 0
SysUser [id=1, userName=admin, userPassword=123456, [email protected], createTime=Mon Oct 01 18:27:36 CST 2018, userInfo=管理員, headImg=null]
3. 儲存過程select_user_page,根據使用者名稱和分頁引數進行查詢,返回總數和分頁資料,使用Map接收出參。有返回值
- 在MYSQL中建立儲存過程select_user_page
CREATE PROCEDURE `select_user_page`(
IN userName VARCHAR(60),
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;
- 在SysUserMapper.xml中新增儲存過程呼叫方法selectUserPage
<!-- 儲存過程的呼叫,返回值使用resultMap指定,使用map接收出參-->
<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>
- 在SysUserMapper介面中新增儲存過程呼叫方法selectUserPage
/**
* 使用儲存過程分頁查詢,根據編號查使用者資訊
* @param params
*/
List<SysUser> selectUserPage(Map<String, Object> params);
- 在UserMaperTest新增selectUserPage測試方法
@Test
public void testSelectUserPage() {
// 獲取SqlSession
SqlSession sqlSession = openSession();
try {
// 獲取SysUserMapper介面
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
// 查詢條件
Map<String, Object> params = new HashMap<>();
params.put("userName", "test");
params.put("offset", 0);
params.put("limit", 10);
// 呼叫selectUserPage方法
List<SysUser> users = userMapper.selectUserPage(params);
// user不為空
Assert.assertNotNull(params.get("total"));
// 查詢使用者資訊
System.out.println(params);
System.out.println(users);
} finally {
sqlSession.close();
}
}
- select_user_page執行結果
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - ==> Preparing: {call select_user_page ( ?, ?, ?, ? )}
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - ==> Parameters: test(String), 0(Integer), 10(Integer)
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - <== Row: 1001, test, 123456, [email protected], <<BLOB>>, <<BLOB>>, 2018-10-02 17:17:11.0
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - <== Total: 1
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserPage] - <== Updates: 0
{total=1, offset=0, limit=10, userName=test}
[SysUser [id=1001, userName=test, userPassword=123456, [email protected], createTime=Tue Oct 02 17:17:11 CST 2018, userInfo=測試使用者, headImg=null]]
4. 儲存過程insert_user_and_roles,儲存使用者資訊和角色關聯資訊
- 在MYSQL中建立儲存過程insert_user_and_roles
CREATE PROCEDURE `insert_user_and_roles`(
OUT userId BIGINT,
OUT createTime DATETIME,
IN userName VARCHAR(60),
IN userPassword VARCHAR(60),
IN userEmail VARCHAR(60),
IN userInfo TEXT,
IN headImg BLOB,
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;
- 在SysUserMapper.xml中新增儲存過程呼叫方法insertUserAndRoles
<!-- 儲存過程的呼叫 ,儲存使用者資訊和角色關聯資訊-->
<insert id="insertUserAndRoles" statementType="CALLABLE">
{call insert_user_and_roles (
#{user.id, mode=OUT, jdbcType=BIGINT},
#{user.createTime, mode=OUT, jdbcType=TIMESTAMP},
#{user.userName, mode=IN},
#{user.userPassword, mode=IN},
#{user.userEmail, mode=IN},
#{user.userInfo, mode=IN},
#{user.headImg, mode=IN, jdbcType=BLOB},
#{roleIds, mode=IN}
)}
</insert>
- 在SysUserMapper介面中新增儲存過程呼叫方法insertUserAndRoles
/**
* 使用儲存過程插入資料,並獲取主鍵
* @param user
* @param roleIds
* @return
*/
int insertUserAndRoles(@Param("user") SysUser user, @Param("roleIds") String roleIds);
- 在UserMaperTest新增insertUserAndRoles測試方法
@Test
public void testInsertUserAndRoles() {
// 獲取SqlSession
SqlSession sqlSession = openSession();
try {
// 獲取SysUserMapper介面
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
// 使用者資訊
SysUser user = new SysUser();
user.setUserName("test3");
user.setUserPassword("myccl210");
user.setUserEmail("[email protected]");
user.setUserInfo("測試儲存過程插入方法");
user.setHeadImg(new byte[]{1,2,3});
user.setCreateTime(new Date());
// 呼叫insertUserAndRoles方法
int row = userMapper.insertUserAndRoles(user, "1,2");
// row 不為空
Assert.assertNotNull(row);
} finally {
sqlSession.commit();
sqlSession.close();
}
}
- insert_user_and_roles 執行結果
[ex.mybatis.rbac.mapper.SysUserMapper.insertUserAndRoles] - ==> Preparing: {call insert_user_and_roles ( ?, ?, ?, ?, ?, ?, ?, ? )}
[ex.mybatis.rbac.mapper.SysUserMapper.insertUserAndRoles] - ==> Parameters: test3(String), myccl210(String), [email protected](String), 測試儲存過程插入方法(String), [email protected](ByteArrayInputStream), 1,2(String)
[ex.mybatis.rbac.mapper.SysUserMapper.insertUserAndRoles] - <== Updates: 2
- insert_user_and_roles 執行結果,資料庫結果
使用者資訊:
使用者角色資訊:
5. 儲存過程delete_user_by_id,刪除使用者資訊和角色關聯資訊
- 在MYSQL中建立儲存過程delete_user_by_id
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;
- 在SysUserMapper.xml中新增儲存過程呼叫方法deleteUserById
<!-- 儲存過程的呼叫 ,刪除使用者資訊和角色關聯資訊 -->
<delete id="deleteUserById" statementType="CALLABLE">
{call delete_user_by_id (#{id, mode=IN})}
</delete>
- 在SysUserMapper介面中新增儲存過程呼叫方法deleteUserById
/**
* 使用儲存過程刪除資料
* @param id
* @return
*/
int deleteUserById(Long id);
- 在UserMaperTest新增deleteUserById測試方法
@Test
public void testDeleteUserById() {
// 獲取SqlSession
SqlSession sqlSession = openSession();
try {
// 獲取SysUserMapper介面
SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class);
// 呼叫deleteUserById方法
int row = userMapper.deleteUserById(1034L);
System.out.println(row);
} finally {
sqlSession.commit();
sqlSession.close();
}
}
- delete_user_by_id執行結果(查資料庫發現剛才插入的1034資料給刪除了)
[ex.mybatis.rbac.mapper.SysUserMapper.deleteUserById] - ==> Preparing: {call delete_user_by_id (?)}
[ex.mybatis.rbac.mapper.SysUserMapper.deleteUserById] - ==> Parameters: 1034(Long)
[ex.mybatis.rbac.mapper.SysUserMapper.deleteUserById] - <== Updates: 1