数据库JSON(JSONB)类型字段映射PO实体类typeHandler
postgresql数据库中常有表字段类型为jsonb的字段,在PO类映射的时候一般会采用java实体类的方式进行交互,使用mybatis进行操作的时候需要重写typeHandler。
·
1 场景描述
postgresql数据库中常有表字段类型为jsonb的字段,在PO类映射的时候一般会采用java实体类的方式进行交互,使用mybatis进行操作的时候需要重写typeHandler。
2 handler类
2.1 JsonbTypeHandler
当jsonb字段值为对象时,即{“a”:1, “b”:2}这种。handler如下:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.postgresql.util.PGobject;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Jsonb转换器
* mapper里json型字段到类的映射。
* 用法一:
* 入库:#{jsonDataField, typeHandler=com.adu.spring_test.mybatis.typehandler.JsonTypeHandler}
* 出库:
* <resultMap>
* <result property="jsonDataField" column="json_data_field" javaType="com.xxx.MyClass" typeHandler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler"/>
* </resultMap>
* <p>
* 用法二:
* 1)在mybatis-config.xml中指定handler:
* <typeHandlers>
* <typeHandler handler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler" javaType="com.xxx.MyClass"/>
* </typeHandlers>
* 2)在MyClassMapper.xml里直接select/update/insert。
*/
@MappedTypes({Object.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class JsonbTypeHandler extends AbstractJsonTypeHandler<Object> {
private final Class<?> type;
public JsonbTypeHandler(Class<?> type) {
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
if (ps != null) {
PGobject jsonObject = new PGobject();
jsonObject.setType("jsonb");
jsonObject.setValue(JSON.toJSONString(parameter));
ps.setObject(i, jsonObject);
}
}
@Override
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object v=rs.getObject(columnName);
return toFill(v);
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object v=rs.getObject(columnIndex);
return toFill(v);
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object v=cs.getObject(columnIndex);
return toFill(v);
}
@Override
protected Object parse(String json) {
return JSON.parseObject(json, this.type);
}
//必须将v转成 PGObject处理
private Object toFill(Object v){
if(v instanceof PGobject){
PGobject p=(PGobject)v;
String pv=p.getValue();
if(StringUtils.isNotEmpty(pv)&&(p.getType().equals("jsonb")||p.getType().equals("json"))) {
return parse(p.getValue());
}
}
return v;
}
@Override
protected String toJson(Object obj) {
return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty);
}
}
2.2 JSONListTypeHandler
当数据库字段类型为列表时,即[{“a”: 1}, {“a”:2}]这种,handler如下:
import com.alibaba.fastjson.JSON;
public class Json2ListTypeHandler extends JsonbTypeHandler {
/**
* 泛型类型
*/
private final Class<?> genericType;
public Json2ListTypeHandler(Class<?> type) {
super(type);
this.genericType = type;
}
@Override
protected Object parse(String json) {
// 重写反序列化方法 默认转list 使用泛型
return JSON.parseArray(json, this.genericType);
}
@Override
protected String toJson(Object obj) {
return super.toJson(obj);
}
}
3 使用方法
3.1 PO类
@TypeDefs({@TypeDef(name = "JsonbTypeHandler", typeClass = JsonbTypeHandler.class),
@TypeDef(name = "Json2ListTypeHandler", typeClass = Json2ListTypeHandler.class)})
public class Demo {
@Column(columnDefinition = "jsonb")
@Type(type = "JsonbTypeHandler")
private A data1;
@Column(columnDefinition = "jsonb")
@Type(type = "Json2ListTypeHandler")
private List<B> data2;
// 更新如果是mybatis-plus时可以不用@TypeDefs和@Column注解,这样框架有点混乱,在@TableName注解后面增加个autoResultMap = true即可,如
@TableName(value = "tbl_bigscreen_incident_safe_index_location", autoResultMap = true)
public class IncidentIndexLocationPo implements Serializable {
private Integer id;
/**
* 模块名称
*/
private String title;
/**
* 指标数组
*/
@TableField(value = "indexs", typeHandler = JSONArrayHandler.class)
private List<Integer> indexs;
/**
* 规则编码
*/
@TableField(value = "incident_codes", typeHandler = JSONArrayHandler.class)
private List<String> incidentCodes;
}
3.2 mapper.xml resultMap映射
<resultMap id="Demo" type="xxx.xxx.Demo">
<id column="id" property="id" />
<result column="a" property="a" typeHandler="xxx.xxx.JsonbTypeHandler" />
</resultMap>
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)