1. 程式人生 > >【MyBatis學習16】自定義型別處理器typeHandlers介紹

【MyBatis學習16】自定義型別處理器typeHandlers介紹

<update id="update" parameterType="twm.mybatisdemo.pojo.User">
    update user set
    username=#{username},password=#{password},address=#{address}  where id=#{id}
</update>

像上面例子,只需要向update方法傳入一個user物件,mybatis利用反射拆開user物件,然後根據物件中的欄位在預處理語句(PreparedStatement)中設定引數,並且根據欄位的型別,使用setXXX()方式設定相應的值。XXX可以是Integer,String,Date等Java型別。
同理,在從結果集(ResultSet)中取出一個值時,將使用rs.getInt、rs.getString、rs.getTimeStamp等方法將資料轉換為Java物件。

那麼問題來了,javaType和jdbcType的轉換關係由誰來定呢?這就是型別處理器(type handlers)的功能所在。
比如java.lang.String轉成JDBC.Varchar,java.lang.Integer轉成JDBC.int。MyBatis使用內建的型別處理器能轉換所有的基本資料型別、基本型別的包裝型別、byte[] 、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java列舉型別等。

不過對於自定義的型別怎麼辦呢?
假設上面的address在資料庫欄位型別是varchar(50),但是在JAVA twm.mybatisdemo.pojo.User類中的address欄位並不是String型別,而是一個自定義的Address

型別:

public class Address {
    String province;
    String city;
    public Address() {}
    public Address(String province, String city) {
        this.province = province;
        this.city = city;
    }
    //getter and setter......
}

碰到這種情況,mybatis基本懵逼了。。。
如果執行的話就報錯誤:

Type handler was null on parameter mapping for property ‘address’. It
was either not specified and/or could not be found for the javaType /
jdbcType combination specified.

address欄位需要傳遞給#{address},而address欄位是Address型別的,MyBatis並不知道該怎樣來處理這個型別的物件。
因此,需要建立一個自定義的型別處理器(TypeHandler)了

1、建立型別處理器:

class AddressTypeHandler extends BaseTypeHandler<Address>{
}

通過ide自動生成程式碼,可以看到父類BaseTypeHandler有四個方法需要我們實現,包括三個get方法,一個set方法。

2、實現get方法
三個get方法都是用於將資料庫獲得的記錄集裡的address欄位轉成java Address型別的物件。
所以我們首先給Address類增加一個構造方法,用途:根據字串生成一個例項物件。

//假設我們儲存在db中的字串是以","號分隔省市關係的
public Address(String address) {  
    if (address != null) {  
        String[] segments = address.split(",");  
        if (segments.length > 1) {  
            this.province = segments[0];
            this.city = segments[1];  
        } 
        else if (segments.length > 0) {  
            this.city = segments[0];  
        }  
    }  
}

然後實現AddressTypeHandler類中的三個get方法:(有強迫症,不喜歡看arg0,arg1。所以順便也改一下

@Override
public Address getNullableResult(ResultSet rSet, String columnName)
        throws SQLException {
    return new Address(rSet.getString(columnName));
}

@Override
public Address getNullableResult(ResultSet rSet, int columnIndex)
        throws SQLException {
    return new Address(rSet.getString(columnIndex));
}

@Override
public Address getNullableResult(CallableStatement cStatement, int columnIndex)
        throws SQLException {
    return new Address(cStatement.getString(columnIndex));
}

3、實現set方法

set方法是用來將java型別轉成資料庫儲存的型別。
這裡我們先實現一下Address類的toString()方法(如果toString另有它用,那麼就另外用一個方法名)

@Override
public String toString() {
    return this.province + "," + this.city;
}

然後實現AddressTypeHandler類中的setNonNullParameter

@Override
public void setNonNullParameter(PreparedStatement pStatement, int index,
        Address address, JdbcType jdbcType) throws SQLException {
    pStatement.setString(index, address.toString());
}

4、在myBatis配置檔案中註冊該類

<!-- 註冊自定義型別處理器 -->
<typeHandlers>
    <typeHandler handler="twm.mybatisdemo.type.AddressTypeHandler" />
</typeHandlers>

這裡有個小插曲,我當時在配置檔案最後插入了這段,結果提示錯誤:

The content of element type “configuration” must match
“(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)”.

原來在configuration裡的標籤,必須按照提示的這個順序寫,不然就報錯。
因此typeHandlers必須放在environments前面,typeAliases後面。
回顧一下,是不是感覺跟序列化/反序列化這套路很相似?

相關推薦

MyBatis學習16定義型別處理器typeHandlers介紹

<update id="update" parameterType="twm.mybatisdemo.pojo.User"> update user set username=#{username},password=#{pa

MyBatis學習筆記5:認識使用typeHandlers配置型別處理器

簡述 註冊了的型別處理器會用於處理下面兩種情形: 為PreparedStatement設定一個引數,將引數從Java型別轉為JDBC型別。 從ResultSet中取出一個值,將結果從JDBC型別轉為Java型別。 型別處理器可分為以下兩類: MyB

MyBatis學習07輸出型別resultType及輸出引數對映resultMap

使用mybatis操作時,對於SQL語句返回結果的處理通常有兩種方式,一種是resultType,另一種是resultMap。 resultType:如果要填充的pojo屬性和資料庫列名完全一致,可採用resultType。如果出現不一致的情況下,系統並不

MyBatis學習17typeHandlers處理enum型別

如果想使用mybatis自帶的列舉類處理,有2種方式,一個是EnumTypeHandler,一個是EnumOrdinalTypeHandler。 區別如下: EnumTypeHandler直接儲存name值。它是mybatis預設的列舉型別轉換器。

機器學習筆記組織映射網絡(SOM)

非線性 每一個 可能 合作 空間 找到 節點 視覺 網格 什麽是自組織映射? 一個特別有趣的無監督系統是基於競爭性學習,其中輸出神經元之間競爭激活,結果是在任意時間只有一個神經元被激活。這個激活的神經元被稱為勝者神經元(winner-takes-all neuron)。這種

Django 第十篇定義驗證規則和中間件

表達式 主動 mixin tex choice direct request lock test 一、Form基本使用 類 字段 is_valid() cleaned_data errors 字段參數: m

Django 第九篇定義的分頁器組件

ota pen mod href render art 頁碼 .get led 一、分頁的實現與使用 class Pagination(object): """ 自定義分頁 """ def __init__(self,current_pa

MyBatis學習15使用MyBatis Generator自動建立程式碼

這兩天需要用到MyBatis的程式碼自動生成的功能,由於MyBatis屬於一種半自動的ORM框架,所以主要的工作就是配置Mapping對映檔案,但是由於手寫對映檔案很容易出錯,所以可利用MyBatis生成器自動生成實體類、DAO介面和Mapping對映檔案。這樣可以省去很多的功夫,將生成的程

金蝶K3Cloud 定義動態表單顯示外部網頁連結。

  前提: 由於想研究下,如何在金蝶K3Cloud中外掛自己的網頁或者BI 或者報表,所以反編譯了一次標準產品的經營分析平臺(BI)在金蝶K3Cloud連結的實現。 第一步: 新建動態表單   第二步: 拖一個面板控制元件,充滿整個動態表單。   第三步: 註

Python web 開發定義使用者認證函式

自定義 使用者認證類,記得之前在mxonline 裡面做過, 主要思路是:  第一步:在seeting 裡面設定自定義的backends    第二步:在user views 裡面寫檢視函式 自定義使用者認證函式要繼承ModelBackend,並且要重寫

Mybatis學習筆記01—Mybatis入門

什麼是Mybatis: Mybatis是一款持久層框架。用於程式與資料庫的之間的互動。 Mybatis和大名鼎鼎的全自動持久層框架Hibernate最大不同的地方在於,Mybatis是半自動的,由開發人員來定製sql語句。 並且相比較Hibernate而言Mybatis

vue筆記2-定義指令

基礎 除了內建指令,Vue.js也允許註冊自定義指令。自定義指令提供一種機制將資料的變化對映為DOM行為。 Vue.js用Vue.directive(id,definition)方法註冊一個全域性自定義指令,它接受兩個引數:指令ID與定義物件。也可以用元件的di

MyBatis學習18使用註解配置Mapper

MyBatis支援使用註解來配置對映的sql語句,這樣可以省掉對映器xml檔案。 一、對映語句 1、insert  比如入門例項中的: public int insert(User user) throws Exception;11<insert id="in

python進階定義庫函式

在python使用過程中,在不同的專案裡,常常會出現頻繁地自定義同一個函式的情況。為了解決這個問題,我們可以選擇建立一個自定義的庫,並將其新增到系統路徑中 具體操作如下: 在任意位置新建一個專案my_libs,並在其中新建python檔案my_lib1和m

Mybatis學習筆記04 Mybatis分頁-多引數傳遞

2018.5.18需求:查詢分頁資料方法一:使用索引按照引數的順序,從0開始mapper:介面:引數名任意方法二:使用註解、mapper:介面:註解的value值要和mapper的佔位引數一致。方法三:使用map(常用)mapper中的引數佔位符要和測試中的map的key,v

Hadoop學習筆記—5.定義型別處理手機上網日誌

一、測試資料:手機上網日誌 1.1 關於這個日誌   假設我們如下一個日誌檔案,這個檔案的內容是來自某個電信運營商的手機上網日誌,檔案的內容已經經過了優化,格式比較規整,便於學習研究。   該檔案的內容如下(這裡我只截取了三行): 1363157993044 18211575961 94-71-

MyBatis學習10高階對映之多對多查詢

  本文來總結一下mybatis中的多對多對映,從第8節的文章中可以看出,使用者表和商品表示多對多關係,它們兩的多對多是通過訂單項和訂單明細這兩張表所關聯起來的,那麼這一節主要來總結一下使用者表和商

MyBatis學習11MyBatis中的延遲載入

1. 什麼是延遲載入   舉個例子:如果查詢訂單並且關聯查詢使用者資訊。如果先查詢訂單資訊即可滿足要求,當我們需要查詢使用者資訊時再查詢使用者資訊。把對使用者資訊的按需去查詢就是延遲載入。

MyBatis學習8MyBatis中的二級快取

1. 二級快取的原理   前面介紹了,mybatis中的二級快取是mapper級別的快取,值得注意的是,不同的mapper都有一個二級快取,也就是說,不同的mapper之間的二級快取是互不影響的。為了更加清楚的描述二級快取,先來看一個示意圖:     從圖中可以看出: sqlSession1去查詢使用

java學習記錄7.定義一個介面ArearInterface,其中包含一個方法,計算面積三角形、矩形、圓形的面積

* 定義一個介面ArearInterface,其中包含一個方法,計算面積 * 定義三個類:三角形、矩形、圓形,分別實現ArearInterface中的方法 * 定義一個主類,將三角形和圓形的面積顯示在螢幕上ArearInterface 介面public interface A