MySQL讀取JSON轉(zhuǎn)換的方式
存儲
mysql5.7+開始支持存儲JSON,后續(xù)不斷優(yōu)化,應(yīng)用也越來越廣泛 你可以自己將數(shù)據(jù)轉(zhuǎn)換成Json String后插入,也可以選擇使用工具, 而mybatis-plus就為此提供了非常簡便的方式, 只需要在字段上加上 @TableField(typeHandler = XxxTypeHandler.class), mybatis-plus就會自動幫你做轉(zhuǎn)換,通用一般就兩個: - 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;
}存在什么問題?
如果使用通用處理器,那對于基礎(chǔ)類型以及對象來說沒有什么問題。
但如果存儲的字段類型是對象集合,那么當你取出來時,會發(fā)現(xiàn)集合中的對象都是JSONObject類型。
最常見的情況就拿出來進行遍歷操作時,會拋出強轉(zhuǎn)異常:
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to ...
因為處理器幫你轉(zhuǎn)換時,并不會存儲你集合的泛型,所以統(tǒng)統(tǒng)都按照Object類型來轉(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)換,這也是當前最普遍的方式,但是對于存在List字段的對象,還需要在XxxMapper.xml中進行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就會將json轉(zhuǎn)換成javaType對應(yīng)的對象集合了
方式二:配置一個Mybatis插件,攔截ResultSetHandler,將返回結(jié)果進行處理。 這樣的好處就是不用寫自定義的處理器和在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;
}
* 將返回數(shù)據(jù)中心的JSONObject對象轉(zhuǎn)換成正常的對象
*
* @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)));
}
* 判斷是否跳過字段
* @param value
* @return
private Boolean isNullValueField(Object value) {
return null == value || "".equals(String.valueOf(value).trim())
|| (value instanceof Collection && ((Collection<?>) value).size() == 0);
* 判斷值是否包含JSONObject對象
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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis攔截器實現(xiàn)分頁功能的實現(xiàn)方法
這篇文章主要介紹了MyBatis攔截器實現(xiàn)分頁功能的實現(xiàn)方法的相關(guān)資料,希望通過本文大家能夠?qū)崿F(xiàn)這樣的方法,需要的朋友可以參考下2017-10-10
textarea標簽(存取數(shù)據(jù)庫mysql)的換行方法
textarea標簽本身不識別換行功能,回車換行用的是\n換行符,輸入時的確有換行的效果,但是html渲染或者保存數(shù)據(jù)庫mysql時就只是一個空格了,這時就需要利用換行符\n和br標簽的轉(zhuǎn)換進行處理2023-09-09
MySQL中的數(shù)據(jù)類型binary和varbinary詳解
binary和varbinary與char和varchar類型有點類似,不同的是binary和varbinary存儲的是二進制的字符串,而非字符型字符串。下面這篇文章主要給大家介紹了關(guān)于MySQL中數(shù)據(jù)類型binary和varbinary的相關(guān)資料,介紹的非常詳細,需要的朋友可以參考學習。2017-07-07
Mysql行轉(zhuǎn)列把逗號分隔的字段拆分成多行兩種方法
在數(shù)據(jù)庫中有時候我們需要將一些行數(shù)據(jù)轉(zhuǎn)換為列數(shù)據(jù),這在處理數(shù)據(jù)透視表、報表生成等場景下非常常見,這篇文章主要給大家介紹了關(guān)于Mysql行轉(zhuǎn)列把逗號分隔的字段拆分成多行的兩種方法,需要的朋友可以參考下2024-05-05
MySQL下高可用故障轉(zhuǎn)移方案MHA的超級部署教程
這篇文章主要介紹了MySQL下高可用故障切換方案MHA的超級部署教程,文中隊MHA方案的一些特點做了介紹,示例基于Linux系統(tǒng)的服務(wù)器環(huán)境,需要的朋友可以參考下2015-12-12

