MySQL读取JSON转换的⽅式
⽬录
存储
存在什么问题?
如何处理
存储
mysql5.7+开始⽀持存储JSON,后续不断优化,应⽤也越来越⼴泛
你可以⾃⼰将数据转换成Json String后插⼊,也可以选择使⽤⼯具,
⽽mybatis-plus就为此提供了⾮常简便的⽅式,
只需要在字段上加上 @TableField(typeHandler = XxxTypeHandler.class),
mybatis-plus就会⾃动帮你做转换,通⽤⼀般就两个:
-
sion.handlers.JacksonTypeHandler
- sion.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;
}
存在什么问题?
如果使⽤通⽤处理器,那对于基础类型以及对象来说没有什么问题。
但如果存储的字段类型是对象集合,那么当你取出来时,会发现集合中的对象都是JSONObject类型。
最常见的情况就拿出来进⾏遍历操作时,会抛出强转异常:
java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to ...
因为处理器帮你转换时,并不会存储你集合的泛型,所以统统都按照Object类型来转换了:
@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 {
// ...
}
}
如何处理
⽅式⼀:⾃定义处理器,⾃⼰做类型转换,这也是当前最普遍的⽅式,但是对于存在List字段的对象,还需要在l中进⾏resultMap配置
@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListFastJsonTypeHandler extends FastjsonTypeHandler {
private final Class<? extends Object> type;
public ListFastJsonTypeHandler(Class<?> type) {
super(type);
}
/**
* ⾃⼰将json转换成list
* @param json
* @return
*/
@Override
protected Object parse(String json) {
return JSON.parseArray(json, pe);
}
<mapper namespace="apper.DepartmentMapper">
<resultMap id="BaseResultMap" type="domain.Department">
<id property="id" column="id"/>
access转mysql教程视频<result property="users" column="users" jdbcType="VARCHAR"
javaType="domain.Department.User"
typeHandler="sion.handlers.FastjsonTypeHandler"/>
</resultMap>
</mapper>
配置完成后,ListFastJsonTypeHandler就会将json转换成javaType对应的对象集合了
⽅式⼆:配置⼀个Mybatis插件,拦截ResultSetHandler,将返回结果进⾏处理。这样的好处就是不⽤写⾃定义的处理器和在l中做配置,减少了⼯作
@Component
@Intercepts({
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class ResultSetInterceptor implements Interceptor {
/**
* json序列化规则
*/
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.JSONString(proceed, serializerFeatures), ((Collection<?>) proceed).toArray()[0].getClass());
}
return JSON.JSONString(proceed, serializerFeatures), Class());
}
// if (proceed instanceof Collection) {
// for (Object obj : ((Collection<?>) proceed)) {
// parseJSON2Object(obj, Class());
// }
// } else {
// parseJSON2Object(proceed, Class());
// }
return proceed;
}
* 将返回数据中⼼的JSONObject对象转换成正常的对象
*
* @param obj
* @param typeClass
* @throws IllegalAccessException
* @throws ClassNotFoundException
private void parseJSON2Object(Object obj, Class<?> typeClass) throws IllegalAccessException, ClassNotFoundException {
for (Field declaredField : DeclaredFields()) {
declaredField.setAccessible(true);
Object value = (obj);
if (isNullValueField(value)) {
continue;
Type genericType = GenericType();
String fieldClassName = TypeName();
if (genericType instanceof ParameterizedType) {
fieldClassName = ((ParameterizedType) genericType).getActualTypeArguments()[0].getTypeName();
if (containJSONObject(value)) {
if (value instanceof Collection) {
declaredField.set(obj, JSON.JSONString(value, serializerFeatures), Class.forName(fieldClassName)));
} else {
declaredField.set(obj, JSON.JSONString(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 : Class().getDeclaredFields()) {
declaredField.setAccessible(true);
Object fieldValue = (obj);
if (isNullValueField(fieldValue)) {
continue;
}
if (fieldValue instanceof JSONObject) {
return true;
if (fieldValue instanceof Collection && containJSONObject(fieldValue)) {
}
return value instanceof JSONObject;
}
到此这篇关于MySQL读取JSON转换的⽂章就介绍到这了,更多相关MySQL读取JSON转换内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论