Mybatis读取和存储json类型数据的实现

 更新时间:2023年06月08日 15:23:32   作者:怪 咖@  
本文主要介绍了Mybatis读取和存储json类型数据的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

不管数据库当中是以json还是longtext数据类型来存json,都可以在mybatis当中使用string来接数据。这一点毋庸置疑!但是想要使用JSONObject类型的字段来取值是否可以呢?

一、测试使用JSONObject来获取json

接下来我们来测试一下,我用的是mybatis-plus框架,mybatis-plus和mybatis是一样的,无非就是mybatis-plus封装好了一些crud方法。但是对于手写xml来说两个框架是一样的。

实体类如下:这里的JSONObject我用的hutool工具包的,JSONObject一般引用的json框架都有

测试接口如下:这里一共写了两个接口,一个接口是手写的,一个是调用的mybatis-plus当中提供的BaseMapper的selectList方法

查询结果如下:假如想要使用JSONObject来映射数据库当中的json数据,不做任何配置是取不到的。

这个是访问mybatis-plus当中提供的查询方法

得出结论:在不做任何配置的情况下,不管是手写的xml接口还是用mybatis-plus自带的查询接口,都是无法将json数据映射到JSONObject类型的字段当中的。

二、设置@TableName的autoResultMap为true,@TableField的typeHandler为JacksonTypeHandler.class

两个接口测试如下:调整过后,mybatis-plus当中自带的接口是可以将json数据映射到JSONObject类型的字段当中的(不管是longtext类型存储的json还是json类型存储的json数据)

对于mybatis-plus框架我们将@TableName的autoResultMap为true,然后@TableField的typeHandler为JacksonTypeHandler.class之后,调用mybatis-plus自带的查询接口是可以将json数据映射到JSONObject类型的字段当中的。

注意:如果@TableName的autoResultMap不设置为true,那么设置typeHandler不会生效

三、设置xml当中的resultMap

使用mybatis,有两个属性标签<resultType><resultMap>可以提供结果映射。

虽然resultType 属性在大部分情况下都够用,但是在一些特殊情况下无能为力,比如属性名和列名不一致,为一些连接的复杂语句编写映射代码。遇到这些情况,我们要使用<resultMap>标签,一份 <resultMap> 能够代替实现同等功能的数千行代码。

resultMap 元素是 MyBatis 中最重要最强大的元素。resultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

注意:这里去掉了<reslutType>属性,用<resultMap>代替,二者只能选择其中的一个。

其实在上面设置@TableName的autoResultMap为true,@TableField的typeHandler为JacksonTypeHandler.class等同于在xml当中配置resultMap的某个属性使用JacksonTypeHandler。只不过mybatis-plus这块使用的是注解的形式,而mybatis应该是没有注解方式的。所以他只能用以下方式:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gzl.cn.mysqljson.mapper.UserMapper">
    <resultMap id="BaseResultMap" type="com.gzl.cn.mysqljson.model.User">
        <id column="id" jdbcType="BIGINT" property="id" />
        <result column="name" jdbcType="VARCHAR" property="name" />
        <result column="age" jdbcType="INTEGER" property="age" />
        <result column="email" jdbcType="VARCHAR" property="email" />
        <result column="result_json" jdbcType="OTHER" property="resultJson" javaType="cn.hutool.json.JSONObject" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
        <result column="result_text" jdbcType="VARCHAR" property="resultText" javaType="cn.hutool.json.JSONObject" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
    </resultMap>
    <select id="getAllList" resultMap="BaseResultMap">
        select * from user
    </select>
</mapper>

查询结果如下:

四、JacksonTypeHandler讲解

JacksonTypeHandler是mybatis-plus提供的,不管是使用注解方式还是使用xml方式当中都使用到了JacksonTypeHandler类。那么这个类到低是干什么的?假如我使用的是mybatis而并不是mybatis-plus该怎么办?

JacksonTypeHandler就是专门用来做数据映射转换的。是mybatis-plus的,但是实际上继承的是BaseTypeHandler,而BaseTypeHandler是mybatis的,那么我们也就可以基于BaseTypeHandler来自己写一个。

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JsonTypeHandler<T> extends BaseTypeHandler<T> {
    private static final ObjectMapper mapper = new ObjectMapper();
    private Class<T> clazz;
    public JsonTypeHandler(Class<T> clazz) {
        if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.clazz = clazz;
    }
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, this.toJson(parameter));
    }
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return this.toObject(rs.getString(columnName), clazz);
    }
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.toObject(rs.getString(columnIndex), clazz);
    }
    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.toObject(cs.getString(columnIndex), clazz);
    }
    private String toJson(T object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private T toObject(String content, Class<?> clazz) {
        if (content != null && !content.isEmpty()) {
            try {
            	// 核心转换,将数据库读取的字符串,转换为指定的class类型
                return (T) mapper.readValue(content, clazz);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            return null;
        }
    }
}

五、新增假如是JSONObject异常问题

而对于 typeHandler 属性,MyBatis 只支持写在 2 个地方:

定义在 resultMap 里,作用于查询结果的封装

定义在 insert 和 update 语句的 #{property} 中的 property后面
(例:#{property,typehandler=xxx.xxx.xxx}),并且只作用于当前 设置值

假如不配置是会报错的!

六、遇到转义的问题

在使用JSONObject作为Java对象的类型存值和取值是可以原样返回的:

那假如是使用的String存值和取值会发生什么样的场景呢?

首先使用String来直接接json对象肯定是不可以的,直接会报400异常。

针对于这个问题有两种方案,一种是对json建立Java对象,还有一种是直接使用JSONObject

假如使用字符串来查询会出现转义的问题

遇到这个问题可以使用commons-lang3包下的StringEscapeUtils.unescapeJava进行转换一下

查询结果如下:

 到此这篇关于Mybatis读取和存储json类型数据的实现的文章就介绍到这了,更多相关Mybatis读取和存储json内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java基于jdbc实现简单学生管理系统

    java基于jdbc实现简单学生管理系统

    本文主要主要介绍了java连接mysql数据库的一个简单学生系统,通过jdbc连接数据库。文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Java如何实现HTTP断点续传功能

    Java如何实现HTTP断点续传功能

    其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已,本文将详细介绍Java如何实现HTTP断点续传功能,需要的朋友可以参考下
    2012-11-11
  • mybatis之增删改查

    mybatis之增删改查

    本篇文章主要介绍了Mybatis实现数据的增删改查实例(CRUD),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-07-07
  • Java ES(Elasticsearch) 中的and 和 or 查询

    Java ES(Elasticsearch) 中的and 和 or 查

    Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎,es中match查询中,查询字符串分词后,默认是or或者的关系,这篇文章主要介绍了ES 中的and 和 or 查询,需要的朋友可以参考下
    2022-11-11
  • Mybatis 实现打印sql语句的代码

    Mybatis 实现打印sql语句的代码

    这篇文章主要介绍了Mybatis 实现打印sql语句的代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 网络爬虫案例解析

    网络爬虫案例解析

    本文主要介绍了网络爬虫的小案例。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • Java虚拟机JVM性能优化(一):JVM知识总结

    Java虚拟机JVM性能优化(一):JVM知识总结

    这篇文章主要介绍了Java虚拟机JVM性能优化(一):JVM知识总结,本文是系列文章的第一篇,后续篇章请继续关注脚本之家,需要的朋友可以参考下
    2014-09-09
  • java 压缩图片(只缩小体积,不更改图片尺寸)的示例

    java 压缩图片(只缩小体积,不更改图片尺寸)的示例

    这篇文章主要介绍了java 如何压缩图片体积,帮助大家更好的利用Java处理图片,应对特殊情况,感兴趣的朋友可以了解下
    2020-10-10
  • java后端把数据转换为树,map递归生成json树,返回给前端(后台转换)

    java后端把数据转换为树,map递归生成json树,返回给前端(后台转换)

    这篇文章主要介绍了java后端把数据转换为树,map递归生成json树,返回给前端实例(后台转换),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-01-01
  • springBoot项目如何实现启动多个实例

    springBoot项目如何实现启动多个实例

    这篇文章主要介绍了springBoot项目如何实现启动多个实例的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论