Mybatis——数据库json字段映射实体类

2年前 (2022) 程序员胖胖胖虎阿
318 0 0

Mybatis——数据库json字段映射实体类

场景:数据库varchar字段存放json格式字符串数据,Mybatis查询解析json数据映射到实体类属性变量。

相关依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.74</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>4.6.10</version>
</dependency>

Json解析工具类:

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sf.nwms.core.util.lang.DateUtil;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.TypeUtil;

/**
 * @Title: JsonUtil
 * @Description: Json工具类,暂时内部使用fastjson实现
 * @version V1.0
 */
public class JsonUtil {
    private JsonUtil() {}

    public static String obj2json(Object obj) {
        return obj2json(obj, DateUtil.DATE_TIME_PATTERN);
    }

    /**
     * 
     * @Description: 
     * @param obj
     * @param beIgnoreNull 是否忽略null值
     * @param beFormat  是否格式化
     * @param dataFormat  指定日期格式化 
     * @return
     */
    public static String obj2json2(Object obj, boolean beIgnoreNull, boolean beFormat, String dataFormat) {
        List<SerializerFeature> features = new ArrayList<>();
        if (!beIgnoreNull) {
            features.add(SerializerFeature.WriteMapNullValue);
            features.add(SerializerFeature.DisableCircularReferenceDetect);
            features.add(SerializerFeature.WriteNullStringAsEmpty);
            features.add(SerializerFeature.WriteNullListAsEmpty);
            features.add(SerializerFeature.WriteDateUseDateFormat);
        }
        if (beFormat) {
            features.add(SerializerFeature.PrettyFormat);
        }
        features.add(SerializerFeature.WriteDateUseDateFormat);
        return obj2json2(obj, dataFormat, features.toArray(new SerializerFeature[] {}));
    }

    public static String obj2json2(Object obj, boolean beIgnoreNull, boolean beFormat) {
        return obj2json2(obj, beIgnoreNull, beFormat, DateUtil.DATE_TIME_PATTERN);
    }

    public static String obj2json2(Object obj, boolean beIgnoreNull) {
        return obj2json2(obj, beIgnoreNull, false);
    }

    public static String obj2json2(Object obj) {
        return obj2json2(obj, false);
    }

    /**
     * 
     * @Description: 对象转json
     * @param obj
     *            对象
     * @param beFormat
     *            是否格式化
     * @return json字符串
     */
    public static String obj2json(Object obj, boolean beFormat) {
        return obj2json2(obj, false, beFormat);
    }

    /**
    * 
    * @Description: 对象转json
    * @param obj
    * @param dataFormat 日期格式
    * @return
    * 
    * 如果java bean的Date类型属性需要特殊处理,使用注解
    * @com.alibaba.fastjson.annotation.JSONField
    */
    public static String obj2json(Object obj, String dataFormat) {
        return obj2json2(obj, false, false, dataFormat);
    }

    private static String obj2json2(Object obj, String dataFormat, SerializerFeature... feature) {
        String defaultFormat = JSONObject.DEFFAULT_DATE_FORMAT;
        JSONObject.DEFFAULT_DATE_FORMAT = dataFormat;
        String json = JSON.toJSONString(obj, feature);
        JSONObject.DEFFAULT_DATE_FORMAT = defaultFormat;
        return json;
    }

    /**
     * 
     * @Description: xml转json
     * @param xml
     * @return json字符串
     */
    public static String xml2json(String xml) {
        return cn.hutool.json.JSONUtil.xmlToJson(xml).toJSONString(0);
    }

    /**
     * 
     * @Description: json转对象
     * @param jsonString
     * @param beanClass
     * @return 实体类对象
     */
    public static <T> T json2Obj(String jsonString, Class<T> beanClass) {
        return JSON.parseObject(jsonString, beanClass);
    }

    /**
     * 
     * @Description JSON字符串转为实体类对象,转换异常将被抛出
     *
     * @param <T>
     *            Bean类型
     * @param jsonString
     *            JSON字符串
     * @param typeReference
     *            {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
     * @param ignoreError
     *            是否忽略错误
     * @return 实体类对象
     */
    public static <T> T json2Obj(String jsonString, com.sf.nwms.core.util.lang.TypeReference<T> typeReference,
        boolean ignoreError) {
        /* return cn.hutool.json.JSONUtil.toBean(jsonString, TypeUtil.getTypeArgument(typeReference.getClass()),
            ignoreError);*/
        return json2Obj(jsonString, typeReference);
    }

    /**
     * 
     * @Description: 
     * @param <T>
     * @param jsonString
     * @param typeReference
     * @return
     * 
     * eg: JsonUtil.json2Obj(jsonString, new com.sf.nwms.core.util.lang.TypeReference<List<JavaBean>())
     */
    public static <T> T json2Obj(String jsonString, com.sf.nwms.core.util.lang.TypeReference<T> typeReference) {
        return JSON.parseObject(jsonString, TypeUtil.getTypeArgument(typeReference.getClass()));
    }

    /**
     * 
     * @Description: json转对象
     * @param jsonString
     *            json字符串
     * @param beanType
     *            实体类对象类型
     * @param ignoreError
     *            是否忽略错误
     * @return 实体类对象
     */
    public static <T> T json2Obj(String jsonString, Type beanType, boolean ignoreError) {
        return JSON.parseObject(jsonString, beanType);
    }

}

mysql存储json的字段类型转换抽象类:

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.alibaba.fastjson.JSON;

/**     
 * @Title: AbstractObjectTypeHandler   
 * @Description: mysql存储json的字段类型转换抽象类 
 */
// @Slf4j
// @MappedJdbcTypes(JdbcType.VARCHAR)
public abstract class AbstractObjectTypeHandler<T> extends BaseTypeHandler<T> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        if (null != parameter) {
            ps.setString(i, JsonUtil.obj2json(parameter));
        }
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return deserialize(rs.getString(columnName));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return deserialize(rs.getString(columnIndex));
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return deserialize(cs.getString(columnIndex));
    }

    /**    
     * @Description: json反序列化
     * @param data
     * @return          
     */
    private T deserialize(String data) {
        return StringUtils.isBlank(data) ? null : string2Obj(data);
    }

    // 重点,解析方法,子类可重写json解析
    @SuppressWarnings("unchecked")
    protected T string2Obj(String jsonString) {
        Class<T> clazz = (Class<T>)getRawType();
        return JSON.parseObject(jsonString, clazz);
    }
}

解析实体

数据库表test:

字段名 类别 参考值
id bigint 1
json_value varchar {name:“张三”,age:14}

正常Mybatis映射实体类:

@Data
public class Test{
    private Long id;
    private String jsonValue;
}

Json内容实体类:

@Data
public class Person{
    private String name;
    private int age;
}

Mybatis映射实体类时,解析json字段数据到变量,改造Test实体类:

@Data
public class Test{
    private Long id;
    
    @ColumnType(jdbcType = JdbcType.VARCHAR, typeHandler = PersonTypeHandler.class)
    private Person jsonValue;
}

添加Json解析转换器:

import com.alibaba.fastjson.JSON;

/**     
 * @Description: Person类型转换器       
 */
public class PersonTypeHandler extends AbstractObjectTypeHandler<Person> {}

Mybatis xml映射

<resultMap type="com.test.model.Test" id="TestMap">
    <result property="id" column="id" jdbcType="INTEGER"/>
    <result typeHandler="com.test.typehandler.PersonTypeHandler" property="jsonValue" column="json_value" jdbcType="VARCHAR"/>
</resultMap>

查询test数据时,使用以上resultMap接收,在映射实体类时自动解析json字段。

解析List

数据库表test:

字段名 类别 参考值
id bigint 1
json_list_value varchar [{name:“张三”,age:14},{name:“李四”,age:15}]

正常Mybatis映射实体类:

@Data
public class Test{
    private Long id;
    private String jsonListValue;
}

Json内容实体类:

@Data
public class Person{
    private String name;
    private int age;
}

Mybatis映射实体类时,解析json字段数据到变量,改造Test实体类:

@Data
public class Test{
    private Long id;
    
    // 映射成List<Person>
    @ColumnType(jdbcType = JdbcType.VARCHAR, typeHandler = ListPersonTypeHandler.class)
    private List<Person> jsonValue;
}

添加Json解析转换器:

import com.alibaba.fastjson.JSON;

/**     
 * @Description: List<Person>类型转换器       
 */
public class ListPersonTypeHandler extends AbstractObjectTypeHandler<List<Person>> {
    @Override
    protected List<Person> string2Obj(String jsonString) {
        return JSON.parseArray(jsonString, Person.class);
    }
}

Mybatis xml映射

<resultMap type="com.test.model.Test" id="TestMap">
    <result property="id" column="id" jdbcType="INTEGER"/>
    <result typeHandler="com.test.typehandler.ListPersonTypeHandler" property="jsonListValue" column="json_list_value" jdbcType="VARCHAR"/>
</resultMap>

查询test数据时,使用以上resultMap接收,在映射实体类时自动解析json集合字段。

版权声明:程序员胖胖胖虎阿 发表于 2022年11月25日 上午10:24。
转载请注明:Mybatis——数据库json字段映射实体类 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...