MyBatis 示例之存儲過程

存儲過程在數據庫中比較常見,雖然大多數存儲過程比較複雜,可是使用 MyBatis 調用時,用法都同樣,所以咱們這一節使用一個簡單的存儲過程來了解 MyBatis 中存儲過程的使用方法。java

基本準備

存儲過程涉及表 sys_user,建表語句以下。sql

DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用戶ID', `user_name` varchar(50) DEFAULT NULL COMMENT '用戶名', `user_password` varchar(50) DEFAULT NULL COMMENT '密碼', `user_email` varchar(50) DEFAULT 'test@mybatis.tk' COMMENT '郵箱', `user_info` text COMMENT '簡介', `head_img` blob COMMENT '頭像', `create_time` datetime DEFAULT NULL COMMENT '建立時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1035 DEFAULT CHARSET=utf8 COMMENT='用戶表';

 

準備測試數據以下。數據庫

INSERT INTO `sys_user` VALUES ('1', 'admin', '123456', 'admin@mybatis.tk', '管理員用戶', 0x1231231230, '2016-06-07 01:11:12'); INSERT INTO `sys_user` VALUES ('1001', 'test', '123456', 'test@mybatis.tk', '測試用戶', 0x1231231230, '2016-06-07 00:00:00');

 

對應實體類SysUser以下:數組

/** * 用戶表 */ public class SysUser implements Serializable { private static final long serialVersionUID = 1L; /** * 用戶ID */ private Long id; /** * 用戶名 */ private String userName; /** * 密碼 */ private String userPassword; /** * 郵箱 */ private String userEmail; /** * 簡介 */ private String userInfo; /** * 頭像 */ private byte[] headImg; /** * 建立時間 */ private Date createTime; //省略 getter 和 setter }

建存儲過程

咱們先建立以下的存儲過程。緩存

# 第一個存儲過程
# 根據用戶 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 ;

 

建立XML方法

<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 元素中調用存儲過程時,因爲存儲過程方式不支持 MyBatis 的二級緩存(後面章節會介紹),爲了不緩存配置致使出錯,咱們直接將 select 元素的 useCache 屬性設置爲 falsemybatis

在存儲過程當中使用參數時,除了寫上必要的屬性名外,還必須指定參數的 mode(模式),可選值爲 IN、OUT、INOUT 三種,入參使用 IN,出參使用 OUT,輸入輸出參數使用 INOUT。從上面代碼能夠輕易看出 IN 和 OUT 的兩種模式的區別,那就是 OUT 模式的參數,必須指定 jdbcType。這是由於在 IN 模式下,MyBatis 提供了默認的 jdbcType,在 OUT 模式下沒有提供,所以必須指定 jdbcType,另外在使用 Oracle 數據庫時,若是入參存在 null 的狀況,那麼也必須指定 jdbcTypeapp

除了上面提到的這幾點外,headImg 還特別設置了 javaType。在 MyBatis 映射的 Java 類中咱們都不推薦使用基本類型,可是數據庫 BLOB 類型對應的 Java 類型咱們一般都是寫成 byte[] 字節數組,由於 byte[] 數組不會有默認值的問題,因此不會影響咱們通常的使用。可是在不指定 javaType的狀況下,MyBatis 默認使用 Byte 類型。因爲咱們使用的 byte 是基本類型,因此設置 javaType的時候,基本類型要使用帶下劃線方式的類型,在這裏就是 byte[]_byte 對應的是基本類型,byte 對應的是 Byte 類型,在使用 javaType 時必定要注意。測試

建立接口

/** * 使用存儲過程查詢用戶信息 * * @param user * @return */ void selectUserById(SysUser user);

 

由於咱們這個存儲過程沒有返回值(不要和出參混淆),因此咱們返回值類型使用 void,若是你把返回值設置爲 SysUser 或 List<SysUser> 也不會報錯,可是任什麼時候候返回值都是 nullspa

編寫測試

@Test public void testSelectUserById(){ SqlSession sqlSession = //獲取SqlSession的方法 try { //這個例子的XML和接口都定義在UserMapper中 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); SysUser user = new SysUser(); user.setId(1L); userMapper.selectUserById(user); Assert.assertNotNull(user.getUserName()); System.out.println("用戶名:" + user.getUserName()); } finally { sqlSession.close(); } }

 

執行測試,輸出以下日誌:日誌

DEBUG [main] - ==>  Preparing: {call select_user_by_id( ?, ?, ?, ?, ?, ?, ? )} DEBUG [main] - ==> Parameters: 1(Long) 用戶名:admin

 

使用出參方式的時候,一般狀況下咱們會使用對象中的屬性接收出參的值,或者使用 Map 類型方法入參接收返回值。這兩種狀況下有很大的區別。當咱們使用 POJO 對象接收出參時,咱們必須保證全部出參在 POJO 中都有對應的屬性存在,不然就會拋出相似 「Could not set property 'xxx'」的錯誤,這是因爲 POJO 對象中不存在出參對應的 setter 方法致使的。使用 Map 類型時就不須要必須存在該屬性,當 Map 接收了存儲過程的出參時,能夠經過 Map 對象的 get("屬性名") 方法獲取出參的值。

錯誤提示

除了上面提到的錯誤外,當你在執行存儲過程時,還可能會遇到下面的錯誤:

Parameter number x is not an OUT parameter

這個錯誤可能的緣由是由於你調用的存儲過程不存在,或者 MyBatis 中寫的出參和數據庫存儲過程的出參對應不上而致使的。

相關文章
相關標籤/搜索