MyBaties存储和查询json格式的数据(实体存储查询版本)

最近在做的功能,由于别的数据库有值,需要这边的不同入口的进来查询,所以需要同步过来,如果再继续一个一个生成列对应处理感觉不方便,如果没有别的操作,只是存储和查询,那就可以用MySql支持的json格式存储了。

MySql的json是5.7之后才可以处理的,所以版本一定要是这个或者比这个高呦!

首先第一步我们需要定义个处理json类型类,可以叫BaseAttributeTypeHandler,来继承BaseTypeHandler这个ibatis的类,一定要定义类型,后期传参用,

java 复制代码
package xx;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.lettuce.core.dynamic.support.ResolvableType;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.Assert;

import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author df
 * @Description: 基础类, 处理mySql字段为json类型
 * @Date 2023/10/19 9:52
 */
public abstract class BaseAttributeTypeHandler<T> extends BaseTypeHandler<Object> {

    private JavaType javaType;

    /**
     * ObjectMapper
     */
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 构造方法
     */
    public BaseAttributeTypeHandler() {
        // 通过class构造一个ResolvableType对象
        ResolvableType resolvableType = ResolvableType.forClass(getClass());
        // 获取对应泛型实体
        Type type = resolvableType.as(BaseAttributeTypeHandler.class).getGeneric() != null ?
                resolvableType.as(BaseAttributeTypeHandler.class).getGeneric().getType() :
                null;
        // 根据对应类型构造出java类型
        javaType = constructType(type);
    }

    private static JavaType constructType(Type type) {
        Assert.notNull(type, "[Assertion failed] - type is required; it must not be null");
        return TypeFactory.defaultInstance().constructType(type);
    }


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSONUtil.toJsonStr(parameter));
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String value = rs.getString(columnName);
        return convertToEntityAttribute(value);
    }

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

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = cs.getString(columnIndex);
        return convertToEntityAttribute(value);
    }

    private Object convertToEntityAttribute(String dbData) {
        // 根据得到的数据判断类型
        if (StrUtil.isEmpty(dbData)) {
            if (List.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptyList();
            } else if (Set.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptySet();
            } else if (Map.class.isAssignableFrom(javaType.getRawClass())) {
                return Collections.emptyMap();
            } else {
                return null;
            }
        }
        return toObject(dbData, javaType);
    }

    private static <T> T toObject(String json, JavaType javaType) {
        Assert.hasText(json, "[Assertion failed] - this json must have text; it must not be null, empty, or blank");
        Assert.notNull(javaType, "[Assertion failed] - javaType is required; it must not be null");
        try {
            // 给对象设置值
            return (T) OBJECT_MAPPER.readValue(json, javaType);
        } catch (com.fasterxml.jackson.core.JsonParseException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (JsonMappingException e) {
            throw new RuntimeException(e.getMessage(), e);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}

定义要存储的json类型的实体类,假如存储个用户信息把,我们就定义了UserSportTypeHandler,然后继承刚才的类BaseAttributeTypeHandler,传入json实体UserSport(你们自己定义的要存储或者查询出来的实体哈)

java 复制代码
public class UserSportTypeHandler extends BaseAttributeTypeHandler<UserSport> {
}

存储时在po实体里添加如下的说明,好让MySql知道是json,这里的typeHandler则定义为UserSportTypeHandler

java 复制代码
   
@Data
public class User {
    
    private Long id;
    
    private String username;

    @TableField(jdbcType = JdbcType.OTHER, typeHandler = UserSportTypeHandler.class)
    private UserSport userSport;

}

新增

调用mybatis插件直接保存即可

java 复制代码
public class UserBusinessImpl extends ServiceImpl<UserMapper, User> implements UserBusiness {

    public Boolean saveSportDataBatch(List<User> users) {
         super.saveBatch(users);
    }

}

测试下,可以哦,直接存储了json的数据

当然还可以存储list以及list<json>这样的格式,可以这样改。

java 复制代码
public class UserSportTypeHandler extends BaseAttributeTypeHandler<List<UserSport>> {
}

也可以在mapper.xml里这样添加,也要指明typeHadler

XML 复制代码
 <insert id="saveBatch" parameterType="java.util.List">
        INSERT INTO user_sport_record (user_sport)
        <foreach collection="list" separator="," item="item">
            VALUES (
                    #{item.userSport,javaType=com.uniigym.Uniiuser.infrastructure.po.HeartDistribute,typeHandler=HeartDistributeTypeHandler,jdbcType=OTHER});
        </foreach>
    </insert>

查询

当然你要是自己在mapper里写,可以在resultMap下里写,示例:

XML 复制代码
<resultMap type="xx.po.User" id="user">
        <result property="id" column="id" jdbcType="INTEGER"/>
      
        <!-- json需要配置如下才能查询出来数据 -->
        <result typeHandler="com.uniigym.Uniiuser.common.config.mybatis.HeartDistributeTypeHandler"
                property="heartDistribute" column="heart_distribute"
                jdbcType="OTHER" javaType="com.uniigym.Uniiuser.infrastructure.po.HeartDistribute"/>
    </resultMap>

这样查询和添加都可以用这个,但是要在sql种指定resultMap的id,但是如果实体上写了 @TableField(jdbcType = JdbcType.OTHER, typeHandler = UserSportTypeHandler.class),就不用在ResultMap标签在定义了。如果都不配置typeHandler则关于json的字段查询出来为空,只有对了查询和保存才可以处理。

相关推荐
最笨的羊羊13 小时前
Flink CDC系列之:JSON 序列化器JsonRowDataSerializationSchemaUtils
json·flink cdc系列·serialization·json 序列化器·rowdata·schemautils
q***498616 小时前
SpringCloud系列教程:微服务的未来 (五)枚举处理器、JSON处理器、分页插件实现
spring cloud·微服务·json
愤怒的山羊2 天前
jetcache List 缓存, json 序列化 泛型解析成了 JsonObject 处理
缓存·json·list
2***d8852 天前
使用 MySQL 从 JSON 字符串提取数据
mysql·oracle·json
TDengine (老段)2 天前
TDengine 转换函数 TO_JSON 用户手册
android·大数据·数据库·json·时序数据库·tdengine·涛思数据
wow_DG2 天前
【Python✨】VS Code 秒开 Python 类型检查:一招 mypy + settings.json 让你的 Bug 原地现形!
python·json·bug
会篮球的程序猿4 天前
html+canvas+thikphp 可视化工具拖拽、编辑生成JSON,渲染成海报图片 完全自定义,支持选择,文字背景色
前端·html·json
倚肆4 天前
Hutool-json 库完整指南
java·json
q***23924 天前
MySQL JSON数据类型全解析(JSON datatype and functions)
android·mysql·json
i_am_a_div_日积月累_5 天前
JSON数据转Excel
json·excel·css3