MySQL讀取JSON轉(zhuǎn)換的方式
存儲(chǔ)
mysql5.7+開(kāi)始支持存儲(chǔ)JSON,后續(xù)不斷優(yōu)化,應(yīng)用也越來(lái)越廣泛 你可以自己將數(shù)據(jù)轉(zhuǎn)換成Json String后插入,也可以選擇使用工具, 而mybatis-plus就為此提供了非常簡(jiǎn)便的方式, 只需要在字段上加上 @TableField(typeHandler = XxxTypeHandler.class), mybatis-plus就會(huì)自動(dòng)幫你做轉(zhuǎn)換,通用一般就兩個(gè): - com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler - com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler
例如
@Data
@TableName(autoResultMap = true)
public class Department implements Serializable {
private static final long serialVersionUID = 203788572415896870L;
@TableField(typeHandler = FastjsonTypeHandler.class)
private List<Integer> userIds;
}存在什么問(wèn)題?
如果使用通用處理器,那對(duì)于基礎(chǔ)類型以及對(duì)象來(lái)說(shuō)沒(méi)有什么問(wèn)題。
但如果存儲(chǔ)的字段類型是對(duì)象集合,那么當(dāng)你取出來(lái)時(shí),會(huì)發(fā)現(xiàn)集合中的對(duì)象都是JSONObject類型。
最常見(jiàn)的情況就拿出來(lái)進(jìn)行遍歷操作時(shí),會(huì)拋出強(qiáng)轉(zhuǎn)異常:
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to ...
因?yàn)樘幚砥鲙湍戕D(zhuǎn)換時(shí),并不會(huì)存儲(chǔ)你集合的泛型,所以統(tǒng)統(tǒng)都按照Object類型來(lái)轉(zhuǎn)換了:
@Override
protected Object parse(String json) {
return JSON.parseObject(json, type);
}例如下面這種形式的類:
@Data
@TableName(autoResultMap = true)
public class Department implements Serializable {
private static final long serialVersionUID = 203788572415896870L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(typeHandler = FastjsonTypeHandler.class)
private List<User> users;
@Data
public static class USer implements Serializable {
// ...
}
}如何處理
方式一:自定義處理器,自己做類型轉(zhuǎn)換,這也是當(dāng)前最普遍的方式,但是對(duì)于存在List字段的對(duì)象,還需要在XxxMapper.xml中進(jìn)行resultMap配置
@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListFastJsonTypeHandler extends FastjsonTypeHandler {
private final Class<? extends Object> type;
public ListFastJsonTypeHandler(Class<?> type) {
super(type);
this.type = type;
}
/**
* 自己將json轉(zhuǎn)換成list
* @param json
* @return
*/
@Override
protected Object parse(String json) {
return JSON.parseArray(json, this.type);
}<mapper namespace="com.xxx.cn.mapper.DepartmentMapper">
<resultMap id="BaseResultMap" type="com.xxx.cn.domain.Department">
<id property="id" column="id"/>
<result property="users" column="users" jdbcType="VARCHAR"
javaType="com.xxx.cn.domain.Department.User"
typeHandler="com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler"/>
</resultMap>
</mapper>配置完成后,ListFastJsonTypeHandler就會(huì)將json轉(zhuǎn)換成javaType對(duì)應(yīng)的對(duì)象集合了
方式二:配置一個(gè)Mybatis插件,攔截ResultSetHandler,將返回結(jié)果進(jìn)行處理。 這樣的好處就是不用寫(xiě)自定義的處理器和在XxxMapper.xml中做配置,減少了工作
@Component
@Intercepts({
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class ResultSetInterceptor implements Interceptor {
/**
* json序列化規(guī)則
*/
private final SerializerFeature[] serializerFeatures = {
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullStringAsEmpty
};
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object proceed = invocation.proceed();
if (containJSONObject(proceed)) {
if (proceed instanceof Collection) {
return JSON.parseArray(JSON.toJSONString(proceed, serializerFeatures), ((Collection<?>) proceed).toArray()[0].getClass());
}
return JSON.parseObject(JSON.toJSONString(proceed, serializerFeatures), proceed.getClass());
}
// if (proceed instanceof Collection) {
// for (Object obj : ((Collection<?>) proceed)) {
// parseJSON2Object(obj, obj.getClass());
// }
// } else {
// parseJSON2Object(proceed, proceed.getClass());
// }
return proceed;
}
* 將返回?cái)?shù)據(jù)中心的JSONObject對(duì)象轉(zhuǎn)換成正常的對(duì)象
*
* @param obj
* @param typeClass
* @throws IllegalAccessException
* @throws ClassNotFoundException
private void parseJSON2Object(Object obj, Class<?> typeClass) throws IllegalAccessException, ClassNotFoundException {
for (Field declaredField : typeClass.getDeclaredFields()) {
declaredField.setAccessible(true);
Object value = declaredField.get(obj);
if (isNullValueField(value)) {
continue;
Type genericType = declaredField.getGenericType();
String fieldClassName = genericType.getTypeName();
if (genericType instanceof ParameterizedType) {
fieldClassName = ((ParameterizedType) genericType).getActualTypeArguments()[0].getTypeName();
if (containJSONObject(value)) {
if (value instanceof Collection) {
declaredField.set(obj, JSON.parseArray(JSON.toJSONString(value, serializerFeatures), Class.forName(fieldClassName)));
} else {
declaredField.set(obj, JSON.parseObject(JSON.toJSONString(value, serializerFeatures), Class.forName(fieldClassName)));
}
* 判斷是否跳過(guò)字段
* @param value
* @return
private Boolean isNullValueField(Object value) {
return null == value || "".equals(String.valueOf(value).trim())
|| (value instanceof Collection && ((Collection<?>) value).size() == 0);
* 判斷值是否包含JSONObject對(duì)象
private boolean containJSONObject(Object value) throws IllegalAccessException {
if (isNullValueField(value)) {
return false;
if (value instanceof Collection) {
for (Object obj : (Collection<?>) value) {
if (obj instanceof JSONObject) {
return true;
if (obj instanceof Collection && containJSONObject(obj)) {
for (Field declaredField : obj.getClass().getDeclaredFields()) {
declaredField.setAccessible(true);
Object fieldValue = declaredField.get(obj);
if (isNullValueField(fieldValue)) {
continue;
}
if (fieldValue instanceof JSONObject) {
return true;
if (fieldValue instanceof Collection && containJSONObject(fieldValue)) {
}
return value instanceof JSONObject;
}到此這篇關(guān)于MySQL讀取JSON轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)MySQL讀取JSON轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql 操作數(shù)據(jù)庫(kù)基礎(chǔ)詳解
這篇文章主要介紹了mysql 操作數(shù)據(jù)庫(kù)基礎(chǔ)詳解,MySQL是一種關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),關(guān)系數(shù)據(jù)庫(kù)將數(shù)據(jù)保存在不同的表中,而不是將所有數(shù)據(jù)放在一個(gè)大倉(cāng)庫(kù)內(nèi),這樣就增加了速度并提高了靈活性2022-08-08
MyBatis攔截器實(shí)現(xiàn)分頁(yè)功能的實(shí)現(xiàn)方法
這篇文章主要介紹了MyBatis攔截器實(shí)現(xiàn)分頁(yè)功能的實(shí)現(xiàn)方法的相關(guān)資料,希望通過(guò)本文大家能夠?qū)崿F(xiàn)這樣的方法,需要的朋友可以參考下2017-10-10
textarea標(biāo)簽(存取數(shù)據(jù)庫(kù)mysql)的換行方法
textarea標(biāo)簽本身不識(shí)別換行功能,回車換行用的是\n換行符,輸入時(shí)的確有換行的效果,但是html渲染或者保存數(shù)據(jù)庫(kù)mysql時(shí)就只是一個(gè)空格了,這時(shí)就需要利用換行符\n和br標(biāo)簽的轉(zhuǎn)換進(jìn)行處理2023-09-09
MySQL中的數(shù)據(jù)類型binary和varbinary詳解
binary和varbinary與char和varchar類型有點(diǎn)類似,不同的是binary和varbinary存儲(chǔ)的是二進(jìn)制的字符串,而非字符型字符串。下面這篇文章主要給大家介紹了關(guān)于MySQL中數(shù)據(jù)類型binary和varbinary的相關(guān)資料,介紹的非常詳細(xì),需要的朋友可以參考學(xué)習(xí)。2017-07-07
MySQL關(guān)閉密碼強(qiáng)度驗(yàn)證功能
本文通過(guò)實(shí)例代碼給大家介紹了mysql關(guān)閉密碼強(qiáng)度驗(yàn)證功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-06-06
Mysql行轉(zhuǎn)列把逗號(hào)分隔的字段拆分成多行兩種方法
在數(shù)據(jù)庫(kù)中有時(shí)候我們需要將一些行數(shù)據(jù)轉(zhuǎn)換為列數(shù)據(jù),這在處理數(shù)據(jù)透視表、報(bào)表生成等場(chǎng)景下非常常見(jiàn),這篇文章主要給大家介紹了關(guān)于Mysql行轉(zhuǎn)列把逗號(hào)分隔的字段拆分成多行的兩種方法,需要的朋友可以參考下2024-05-05
MySQL下高可用故障轉(zhuǎn)移方案MHA的超級(jí)部署教程
這篇文章主要介紹了MySQL下高可用故障切換方案MHA的超級(jí)部署教程,文中隊(duì)MHA方案的一些特點(diǎn)做了介紹,示例基于Linux系統(tǒng)的服務(wù)器環(huán)境,需要的朋友可以參考下2015-12-12

