MyBatis 示例之儲存過程

JAVA全棧發表於2017-12-21

儲存過程在資料庫中比較常見,雖然大多數儲存過程比較複雜,但是使用 MyBatis 呼叫時,用法都一樣,因此我們這一節使用一個簡單的儲存過程來了解 MyBatis 中儲存過程的使用方法。

基本準備

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

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='使用者表';1234567891011 準備測試資料如下。

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');12 對應實體類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}1234567891011121314151617181920212223242526272829303132333435 建儲存過程

我們先建立如下的儲存過程。

第一個儲存過程

根據使用者 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_timeINTO userName,userPassword,userEmail,userInfo,headImg,createTime from sys_userWHERE id = userId;END;; DELIMITER ;12345678910111213141516171819202122 建立XML方法

1234567891011 在呼叫儲存過程的方法中,我們需要把 statementType 設定為 CALLABLE,在使用select 元素中呼叫儲存過程時,由於儲存過程方式不支援 MyBatis 的二級快取(後面章節會介紹),為了避免快取配置導致出錯,我們直接將 select 元素的useCache 屬性設定為 false。

在儲存過程中使用引數時,除了寫上必要的屬性名外,還必須指定引數的 mode(模式),可選值為 IN、OUT、INOUT 三種,入參使用 IN,出參使用 OUT,輸入輸出引數使用 INOUT。從上面程式碼可以輕易看出 IN 和 OUT 的兩種模式的區別,那就是 OUT 模式的引數,必須指定 jdbcType。這是因為在 IN 模式下,MyBatis 提供了預設的jdbcType,在 OUT 模式下沒有提供,因此必須指定 jdbcType,另外在使用 Oracle 資料庫時,如果入參存在 null 的情況,那麼也必須指定jdbcType。

除了上面提到的這幾點外,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);1234567 因為我們這個儲存過程沒有返回值(不要和出參混淆),所以我們返回值型別使用 void,如果你把返回值設定為 SysUser或 List 也不會報錯,但是任何時候返回值都是 null。

編寫測試

@Testpublic 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(); } }123456789101112131415 執行測試,輸出如下日誌:

DEBUG [main] - ==> Preparing: {call select_user_by_id( ?, ?, ?, ?, ?, ?, ? )} DEBUG [main] - ==> Parameters: 1(Long) 使用者名稱:admin123 使用出參方式的時候,通常情況下我們會使用物件中的屬性接收出參的值,或者使用Map 型別方法入參接收返回值。這兩種情況下有很大的區別。當我們使用 POJO 物件接收出參時,我們必須保證所有出參在 POJO 中都有對應的屬性存在,否則就會丟擲類似“Could not set property 'xxx'”的錯誤,這是由於 POJO 物件中不存在出參對應的 setter 方法導致的。使用 Map 型別時就不需要必須存在該屬性,當 Map 接收了儲存過程的出參時,可以通過 Map 物件的 get("屬性名") 方法獲取出參的值。

錯誤提示

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

Parameter number x is not an OUT parameter

這個錯誤可能的原因是因為你呼叫的儲存過程不存在,或者 MyBatis 中寫的出參和資料庫儲存過程的出參對應不上而導致的。

一個程式設計師學習平臺分享給你們,讓你在實踐中積累經驗掌握原理。主要方向是JAVA工程師。如果你想拿高薪,想突破瓶頸,想跟別人競爭能取得優勢的,想進BAT但是有擔心面試不過的,可以加我的Java學習交流群:450936584

注:加群要求

1、大學學習的是Java相關專業,畢業後面試受挫,找不到對口工作可以 2、在公司待久了,現在過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的 3、參加過線下培訓後,知識點掌握不夠深刻,就業困難,想繼續深造 4、已經在Java相關部門上班的在職人員,對自身職業規劃不清晰,混日子的 5、有一定的C語言基礎,接觸過java開發,想轉行的 小號勿擾,不喜勿加

相關文章