mybatis&plus系列——Mysql的JSON字段的讀取和轉換

mybatis&plus系列——Mysql的JSON字段的讀取和轉換



一. 背景

在平常的開發中,我們可能會有這樣的需求:

業務數據在存儲的時候,並不是以mysql中的varcharint等格式來存儲的,而是使用json格式.

這樣做的好處是當數據結構有變化或者需求變化時,我們不用再添加字段,方便擴展.

那麼mysql中json格式的數據我們使用mybatis或者mybatisplus讀取以後,肯定是希望轉換成對象或者對象集合的,本篇博文就記錄一下使用mybatis讀取json格式的數據轉換為對象的方法

二. 數據準備

1. json字段的添加

首先我們如果要使用sql語句來在表中添加一個json格式的字段,可以使用以下腳本:

ALTER TABLE a ADD COLUMN alert_up_config json DEFAULT NULL COMMENT '注釋' AFTER id

以上sql執行以後,會在a表的id字段之後,添加一個字段alert_up_config,它的格式就是json

添加完成以後,我們可以在這個字段中保存json對象或者json數組格式的字符串.

當前的業務場景是: alert_up_config字段中,是個jsonArr,保存的是告警的升級規則,比如持續時間,次數等.

模擬數據如下:

[{"alertNum": 100, "alertLevel": "P1", "durationTime": 100, "resourceInfoId": "123456"}]

注意,使用json類型有2點需要注意:

  1. 存儲數據必須是json格式,否則會報錯
  2. json數據類型沒有默認值

三. 數據處理

1. 使用sql語句獲取json數據

首先我們可以使用sql語句來提取我們需要的json字段,語法如下:

#json對象類型處理
JSON_EXTRACT(json列, '$.鍵')
#jsonArray類型處理, index從0開始計算
JSON_EXTRACT(json列, '$[index].鍵')

比如對於我們上面的示例數據,我們要查詢出alert_up_config字段中的alertNum的值,可以使用如下語句:

select JSON_EXTRACT(alert_up_config, '$[0].alertNum') from a;

查詢結果如下:

image-20210313143005327

2. 使用mybatis&mybatisPlus來讀取數據庫中的json數據

首先我們需要知道的是,mybatis提供了一個接口org.apache.ibatis.type.TypeHandler來對數據庫中各種類型數據的處理,它主要有四個方法:

public interface TypeHandler<T> {
	
  //保存數據到數據庫之前的處理  
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  //下面三個時候拿到數據以後的處理
  T getResult(ResultSet rs, String columnName) throws SQLException;

  T getResult(ResultSet rs, int columnIndex) throws SQLException;

  T getResult(CallableStatement cs, int columnIndex) throws SQLException;

}

也就是說,如果我們要處理從mysql中取出的數據,就可以實現這個接口,來自定義我們的數據處理邏輯,得到我們想要的數據.

現在對於我們來說,我們的源數據是這樣的:

[{"alertNum": 100, "alertLevel": "P1", "durationTime": 100, "resourceInfoId": "123456"}]

也有可能是這樣的:

{"alertNum": 100, "alertLevel": "P1", "durationTime": 100, "resourceInfoId": "123456"}

前者是JSONArray,後者是JSONObject

對於前面的數據,我們可能會用List<AlertUpConfig>這種格式來接收,如果是後者,我們可以使用AlertUpConfig這種對象來直接接收數據.

現在,我們的需要mybatis或者mybatisplus幫助我們將數據庫中的json數據自動轉換為相應的格式,一起來看下怎麼實現吧!

3. 使用mybatisplus實現json轉java對象/集合

在mybatisplus中,已經為我們提供了一系列的TypeHandler

有一個抽象類為: com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler

它抽象了json處理的方法:

    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, this.toJson(parameter));
    }

    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return StringUtils.isBlank(json) ? null : this.parse(json);
    }

    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return StringUtils.isBlank(json) ? null : this.parse(json);
    }

    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return StringUtils.isBlank(json) ? null : this.parse(json);
    }

同時,它提供兩個抽象方法,用於提供給不同的json包:

    protected abstract T parse(String json);

    protected abstract String toJson(T obj);

我們看一下AbstractJsonTypeHandler的實現類,可以發現有我們想要的東西:

image-20210313144551767

很明顯,mybatisplus已經提供了FastJsonGsonJackSon的typehandler給我們使用.

下面是使用方法:

  • json轉java對象

    如果不用xml文件(xml的方式在mybatis部分說明),在實體對象相應的字段上,用typeHandler參數指定我們要使用的typeHandler

    同時,在實體類上使用註解: @TableName(value = "a", autoResultMap = true)

    autoResultMap 參數表明字段在查詢處理的時候自動轉換為對象

        @TableField(value = "alert_up_config",
                typeHandler = FastjsonTypeHandler.class)
        private AlertUpConfig alertUpConfig;
    

    配置好以後,使用mapper查詢,可以發現alert_up_config字段直接被轉換成了java對象

  • json轉List

4. 使用mybatis在xml中實現json轉java對象/集合

在xml中實現json和對象的轉換也比較簡單

<result column="alert_up_config" property="alertUpConfig" jdbcType="VARCHAR"
                javaType="com.xxxx.AlertUpConfig"
                 typeHandler="com.xxxx.AlertUpConfigHandler"/>

同樣的handler,只是配置方式從註解改成xml中的屬性了.

需要注意的是,FastjsonTypeHandler是mybatisplus提供的處理器,如果你的項目中沒有引入mp,那麼可以自己參照它寫一個.

結語:

在本篇博文中,介紹了數據庫json字段和java對象,以及集合對象的相關轉換,記錄在這裡,以後有需要的時候可以及時查閱

個人公眾號<橙耘自留地>日前已經開通,後續博主發佈的文章都會一併更新到公眾號,如有需要,自行查閱.

關於橙耘自留地,是我個人聚焦互聯網技術棧學習分享的一個平台,創立之初是因為目前業內各種技術課程資料層次不齊,褒貶不一,有時候一門課花費高價買入,其實內含草包,有時偶爾低價得之,卻又大有乾貨.因此我會根據大家的意見和評價,選擇不同的技術棧去學習,一為提升我自己的技術,二為大家梳理出質量比較好的課程,以作參考.同時,相關的學習心得也會一併更新到博客和公眾號.

qrcode_for_gh_c1462e34b232_344