问题的诞生
有些业务场景下,数据库中字符串字段要存一个json,比方说:商品的展示图片集合、文档的附件集合之类的。
那么就会出现这种情况- -
@Data
@Accessors(chain = true)
public class ProductVO implements Serializable {
private static final long serialVersionUID = 6421692337875809507L;
/**
* 展示图片
*/
private List<String> images;
}
@Data
@Accessors(chain = true)
@TableName(value = "product")
public class ProductDO implements Serializable {
private static final long serialVersionUID = 6421692337875809507L;
/**
* 展示图片[json]
*/
private String images;
}
增加、更改、查询的时候都要手动去转换…感觉十分的麻烦!!!
问题的解决
解决环境
Spring Boot 2.3.2 MyBatis Plus 3.4.1
其实产生问题的原因就是:我们通过ORM操作数据库时,给他和拿到的东西数据类型不一致…
然后我就搜orm层能不能解决这个问题 - - 最后找到了…typeHandler就是解决这个问题的!!
代码如下
抽象的typeHandler类:
/**
* @Author:cyw
* @CreateTime: 2021/3/3 17:18
**/
@MappedTypes(List.class)
@MappedJdbcTypes(value = {JdbcType.BLOB, JdbcType.VARCHAR, JdbcType.CHAR})
public abstract class ListJsonTypeHandler<T> extends BaseTypeHandler<List<T>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, serializer(parameter));
}
@Override
public List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
String info = rs.getString(columnName);
return deserializer(info);
}
@Override
public List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return deserializer(rs.getString(columnIndex));
}
@Override
public List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return deserializer(cs.getString(columnIndex));
}
private String serializer(List<T> parameter) {
return JsonUtils.toJsonIfPresent(parameter);
}
protected List<T> deserializer(String info) {
throw new BaseException("根据泛型类型 重写反序列化方法");
}
}
子类指定泛型
/**
* @Author:cyw
* @CreateTime: 2021/3/3 20:58
**/
public class ListString2JsonTypeHandler extends ListJsonTypeHandler<String> {
@Override
protected List<String> deserializer(String info) {
return BaseUtils.isEmpty(info) ? Lists.newArrayList() : JsonUtils.toListIfPresent(info, String.class);
}
}
如何要写个抽象的类
害… 还不是List泛型擦除导致的… 要是不清楚泛型擦除的各位,可以百度下
我们现在举例的场景是String类型,要是下次处理Long或者是自定义的对象,我们直接继承这个抽象typeHandler指定泛型,去重写反序列化方法就好了!!
代码整完之后,就要开始配置咯
指定上面类所在的包路径
mybatis:
type-handlers-package: xxxxx
MP下使用
@Data
@Accessors(chain = true)
@TableName(value = "product", autoResultMap = true)
public class ProductDO implements Serializable {
private static final long serialVersionUID = 6421692337875809507L;
/**
* 展示图片[json]
*/
@TableField(typeHandler = ListString2JsonTypeHandler.class)
private List<String> images;
}
注意了!
除了使用@TableField注解指定 所需的TypeHandler类
还要在@TableName注解里配置 autoResultMap 的属性
我这边举了MP的使用情况,mybatis的使情况也差不多…无非就是mp基于注解的形式 mybatis基于xml去指定,主要是我们去想清楚 这种通用的处理方法应该在哪一步…然后再去想办法去找解决方案去解决!!!拒绝无脑搬砖
相关代码
其实这个项目是我常用的工具类,大家可以clone下来看看,有啥好的想法或者好用的工具类可以pr下或者留下评论!当然点个star最好啦 嘻嘻嘻嘻