mybatis&plus系列——Mysql的JSON字段的讀取和轉換
- 2021 年 3 月 13 日
- 筆記
- json轉java對象, mybatis&mybatisplus, mybatisplus處理json數據, mybatis處理json數據, MySQL
mybatis&plus系列——Mysql的JSON字段的讀取和轉換
一. 背景
在平常的開發中,我們可能會有這樣的需求:
業務數據在存儲的時候,並不是以mysql中的varchar
丶int
等格式來存儲的,而是使用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點需要注意:
- 存儲數據必須是json格式,否則會報錯
- 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;
查詢結果如下:
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
的實現類,可以發現有我們想要的東西:
很明顯,mybatisplus已經提供了FastJson
、Gson
和JackSon
的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對象,以及集合對象的相關轉換,記錄在這裡,以後有需要的時候可以及時查閱
個人公眾號<橙耘自留地>日前已經開通,後續博主發佈的文章都會一併更新到公眾號,如有需要,自行查閱.
關於橙耘自留地,是我個人聚焦互聯網技術棧學習分享的一個平台,創立之初是因為目前業內各種技術課程資料層次不齊,褒貶不一,有時候一門課花費高價買入,其實內含草包,有時偶爾低價得之,卻又大有乾貨.因此我會根據大家的意見和評價,選擇不同的技術棧去學習,一為提升我自己的技術,二為大家梳理出質量比較好的課程,以作參考.同時,相關的學習心得也會一併更新到博客和公眾號.