Mybatis自定義TypeHandler向數據庫中插入Blob數據

一、引言

最近在做一個客戶端日誌統計分析的模塊,被Java實體類中屬性類型與數據庫字段屬性匹配問題搞的頭大。抽個時間,對Mybatis中自定義TypeHandler做一個總結吧。

簡單描述一下需求:客戶端上報日誌接口中,有一個異常內容字段,對應Java實體類excepContent屬性,類型爲String(此處應該定義爲byte[]類型),對應的數據庫中的字段爲excp_content,類型爲blob。

當我們拿到這樣一個實體類往數據庫中插入數據時,毫無疑問,會報類型不匹配異常,讀取時也會報異常。

二、自定義TypeHandler

上面的問題怎麼解決呢?這就需要自定義一個TypeHandler類型處理器。實現TypeHandler接口或繼承BaseTypeHander都可以。

@MappedJdbcTypes(JdbcType.BLOB) // 聲明數據庫中對應數據類型
@MappedTypes(value = String.class) // 轉化後的數據類型
public class CustomBlobTypeHandler extends BaseTypeHandler<String> {

	// 數據插入數據庫時調用此方法
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, 
    				String parameter, JdbcType jdbcType)
            throws SQLException {
        // 聲明一個輸入流對象
        ByteArrayInputStream bis = null;
        try {
            // 把字符串轉爲字節流
            bis = new ByteArrayInputStream(parameter.getBytes("gbk"));
        } catch (Exception e) {
            throw new RuntimeException("Blob Encoding Error!");
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    throw new RuntimeException("Blob Encoding Error!");
                }
            }
        }
        ps.setBinaryStream(i, bis, parameter.length());
    }


	// 從數據庫中讀取數據時調用此方法
    @Override
    public String getNullableResult(ResultSet rs, String columnName) 
    		throws SQLException {
        Blob blob = (Blob) rs.getBlob(columnName);
        byte[] returnValue = null;
        if (null != blob) {
            returnValue = blob.getBytes(1, (int) blob.length());
        }
        try {
            //將取出的流對象轉爲utf-8的字符串對象
            return new String(returnValue, "gbk");
        } catch (Exception e) {
            throw new RuntimeException("Blob Encoding Error!");
        }
    }

	// 讀取方法同上,方法重載
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) 
    			throws SQLException {
        Blob blob = (Blob) rs.getBlob(columnIndex);
        byte[] returnValue = null;
        if (null != blob) {
            returnValue = blob.getBytes(1, (int) blob.length());
        }
        try {
            // 將取出的流對象轉爲utf-8的字符串對象
            return new String(returnValue, "gbk");
        } catch (Exception e) {
           throw new RuntimeException("Blob Encoding Error!");
        }
    }

	// 讀取方法同上,方法重載
    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) 
    		throws SQLException {
        Blob blob = (Blob) cs.getBlob(columnIndex);
        byte[] returnValue = null;
        if (null != blob) {
            returnValue = blob.getBytes(1, (int) blob.length());
        }
        try {
            //將取出的流對象轉爲utf-8的字符串對象
            return new String(returnValue, "gbk");
        } catch (Exception e) {
           throw new RuntimeException("Blob Encoding Error!");
        }
    }
}

自定義的TypeHandler類型處理器寫好了,很簡單。但怎麼讓這個自定義處理器起作用呢?這就需要在配置文件中配置。

三、如何配置

關於如何讓自定義TypeHandler生效,分兩種情況。一種是Mybatis配置,另一種是tk.mybatis配置。

1、Mybatis配置

此情況下,又分爲兩種情況。
(1)、全局配置

mybatis:
  config-location: classpath:mybatis-config.xml  # mybatis配置文件位置
  mapperLocations: classpath:mapper/*.xml # mybatis mapper文件位置
  typeAliasesPackage: com.example.domain # java實體類所在包
  type-handlers-package: com.scorpios.analyse.typehandler # 自定義TypeHandler所在包

此種配置方式,全局有效,不用其他任何配置。

(2)、局部配置:在處理某個字段時,設置typeHandler。比較繁瑣。

在數據插入時,我們可以做如下指定:

#{excpContent,typeHandler="com.scorpios.analyse.typehandler.CustomBlobTypeHandler"}

數據讀取時,我們可以用<resultMap>來封裝,在屬性後面指定typeHandler屬性即可。

<result column="excp_content" property="excpContent" typeHandler="com.scorpios.analyse.typehandler.CustomBlobTypeHandler" />

注意:如果在參數位置修改TypeHandler,應該保證保存數據和查詢數據用的TypeHandler是一樣的。

2、tk.mybatis配置

(1)、全局級別:在 MyBatis 配置文件中配置 typeHandlers。和上述全局配置一樣。

(2)、字段級別:@ColumnType 註解

@ColumnType(typeHandler=CustomBlobTypeHandler .class)
private String excpContent;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章