mybatis&plus系列------Mysql的JSON欄位的讀取和轉換

劍小純發表於2021-03-13

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

相關文章