一 属性添加注解
- 在类上面添加注解:
@TableName(autoResultMap = true)
- 在字段上面添加注解:
@TableField(value = "list", typeHandler = UserHandler.class) private List<User> list = new ArrayList<>();
二 创建 UserHandler 类
java
package com.demo.handler;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.demo.domain.pojo.User;
import org.apache.ibatis.type.MappedTypes;
import java.util.List;
@MappedTypes({List.class, User.class})
public class UserHandler extends AbstractJsonTypeHandler<List<User>> {
@Override
protected List<User> parse(String json) {
return JsonUtils.fromString(json, List.class, User.class);
}
@Override
protected String toJson(List<User> obj) {
return JsonUtils.objectToString(obj);
}
}
如果在使用改类时,只需将文件中的 User 替换为自己的类就行
概括下,这个解析器中的 parse 方法类似咱们的 set 方法,是将数据库中的 json 类型数据转为 List 类型数据;反之,toJson 是将 List 类型数据转为 json 数据格式,最后通过 mybatisplus 存储到数据库中. 具体实现可以看下面的 JsonUtils 工具类.
java
package com.demo.handler;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
public class JsonUtils {
private static final ObjectMapper objectMapper = new ObjectMapper();
//初始化相关的配置
static {
//只引用不为空的值
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
//取消默认转换timestemp
objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
//忽略空bean转换错误
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//忽略在json中存在,在java对象不存在的错误
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 解决jackson2无法反序列化LocalDateTime的问题
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
}
/**
* 将java对象转换成json字符串
*
* @param obj java 对象
* @param <T>
* @return
*/
public static <T> String objectToString(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
/**
* 将json字符串转换成java对象
*
* @param json 字符串
* @param tClass 要转换的对象
* @param <T>
* @return
*/
public static <T> T getObjetFormString(String json, Class<T> tClass) {
if (StringUtils.isBlank(json) || tClass == null) {
return null;
}
try {
return tClass.equals(String.class) ? (T) json : objectMapper.readValue(json, tClass);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 将字符串转换成java对象
*
* @param json 字符串
* @param tTypeReference 对象
* @param <T>
* @return
*/
public static <T> T fromString(String json, TypeReference<T> tTypeReference) {
if (StringUtils.isBlank(json) || tTypeReference == null) {
return null;
}
try {
return tTypeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, tTypeReference);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 将json字符串转换成java集合对象
*
* @param json 字符串
* @param collectionClass 集合类型
* @param elementClazzes 成员类型
* @param <T>
* @return
*/
public static <T> T fromString(String json, Class<?> collectionClass, Class<?>... elementClazzes) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClazzes);
try {
return objectMapper.readValue(json, javaType);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
该文件是工具类,配合 UserHandler 类,无需任何改动,直接粘贴即可
三 数据库字段设置
这里只需要将对应的字段类型设置为 json 即可,这里就不贴图了.
额外说明一个事情,可以说是一个 bug,上述效果在 selectById 查询时是成功的,但是在查询返回体是 List 时,list 字段会返回空集合,问了下 ai,说是数据库为了简洁高效,会跳过解析器,断点测试也确实是这样,至于如何解决,我现在是循环单个查询,最后合并,实属无奈,如果有哪位兄弟能搞定,还麻烦大致说下原因.
文章仓促就之,是在已经已经实现的代码上直接说明,如有读者发现文章有不足或是无法实现效果,可以留言.
如果文章确实有效,还望读者点赞收藏,感谢~