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的字段查询出来为空,只有对了查询和保存才可以处理。

相关推荐
极地星光18 小时前
JSON-RPC-CXX深度解析:C++中的远程调用利器
c++·rpc·json
Amd7941 天前
Nuxt.js 应用中的 schema:beforeWrite 事件钩子详解
json·vite·配置·nuxt·验证·钩子·动态
白萝卜弟弟1 天前
【MySQL】MySQL函数之JSON_EXTRACT
数据库·mysql·json
B1nna2 天前
SpringMVC学习记录(三)之响应数据
java·学习·json·springmvc·jsp
1024小神2 天前
package.json中“type“: “module“是什么含义,es6和commonjs的区别以及require和import使用场景
前端·json·es6
慧都小妮子2 天前
借助Aapose.Cells ,在 Node.js 中将 Excel 转换为 JSON
node.js·json·excel·aspose.cells
杜杜的man2 天前
【go从零单排】JSON序列化和反序列化
golang·json
我是苏苏2 天前
Web开发:ABP框架6——appsetting.json的读取以及实例的注入
前端·windows·json
Mephisto.java2 天前
【大数据学习 | HBASE高级】rowkey的设计,hbase的预分区和压缩
大数据·sql·mysql·json·hbase·database
乐闻x2 天前
ESLint 使用教程(七):ESLint还能校验JSON文件内容?
前端·javascript·json·eslint