首页 > 其他分享 >Mybatis读取和存储json类型的数据

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

时间:2024-09-12 13:53:20浏览次数:10  
标签:读取 JSONObject clazz mybatis json plus Mybatis JacksonTypeHandler

目录
一、测试使用JSONObject来获取json
二、设置@TableName的autoResultMap为true,@TableField的typeHandler为JacksonTypeHandler.class
三、设置xml当中的resultMap
四、JacksonTypeHandler讲解
五、新增假如是JSONObject异常问题
六、遇到转义的问题
不管数据库当中是以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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
查询结果如下:


四、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;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
五、新增假如是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进行转换一下


查询结果如下:


————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_43888891/article/details/130438841

标签:读取,JSONObject,clazz,mybatis,json,plus,Mybatis,JacksonTypeHandler
From: https://www.cnblogs.com/xiaoxihebei/p/18410022

相关文章

  • 滚雪球学MyBatis(12):常见问题与解决方案
    前言欢迎回到我们的MyBatis系列教程。在前几期中,我们已经进行了MyBatis的基础使用、进阶功能及项目实战的详细讲解。通过这些内容,相信大家对MyBatis有了全面的了解,并能够在实际项目中应用MyBatis。然而,在使用MyBatis的过程中,我们可能会遇到各种问题。本期内容中,我们将总结......
  • 滚雪球学MyBatis(13):总结与展望
    前言欢迎回到我们的MyBatis系列教程。在前几期中,我们从基础到进阶,详细讲解了MyBatis的各个方面,并通过项目实战帮助大家巩固所学知识。本期内容中,我们将对整个系列教程进行总结与回顾,并展望未来的学习方向。通过这一期的内容,希望大家能够全面回顾MyBatis的核心知识点,并了解......
  • JsonConfigurationFileParser
    internalclassProgram{staticasyncTaskMain(string[]args){varroot=newRoot{Demo1=newDemo1{Name="Demo1",Data=newDemo2{Name="Demo2"......
  • fastjson1.2.24反序列化漏洞复现 CVE-2017-18349
    1.准备:1.1复现环境漏洞环境:vulnhub靶场工具准备:jdk8,apache-maven-3.9.9,kali2024.1,MarshalSec1.2环境启动进入vulnhub目录下的fastjson目录,进入CVE-2017-18349目录cd/home/hbesljx/vulhub/fastjson/1.2.24-rcedocker-compoe启动漏洞环境docker-composeup-d访问靶机......
  • Web前端与物联网虚拟仿真系统对接读取与控制
    面对学生学习前端开发困难,教师难管理的问题,我们开发了一套Web前端开发实训平台。方便教师与学生进行网站的发布与浏览,平台具备在线CODE编辑器,直接输入代码完成前端开发代码的编写,系统自动生成预览的效果界面。该实训平台能与我们的物联网仿真系统联动,实现虚实结合。物联网......
  • Android +本地文件写入读取解析(传感器ID)
    代码:///<summary>///传感器ID///</summary>publicDictionary<string,string>SensorIDDic=newDictionary<string,string>();publicstringcontents="pen,241007|bookL,240806|bookR,241000";///<summary&......
  • python读取Excel表格内容
    importpandasaspdio=r'C:\Users\lijj1\Downloads\OSS.xlsx'#绝对路径。PS:跟当前脚本在同一目录下用相对路径,否则用绝对路径。data=pd.read_excel(io,sheet_name='工作表1')#指定读取第一个sheetprint(data.head(2))#读取前2行column_data=data.loc[:,'对应域......
  • 【高级编程】Java IO流(下)字符流 Reader Writer 字节流读取二进制文件
    文章目录ReaderFileReaderBufferedReaderWriterFileWriterBufferedWriter读写二进制文件ReaderReader是一个抽象类,用于读取字符流。它是所有字符输入流的基类。Reader提供了一些基本的方法来读取字符数据intread()//读取单个字符,并返回一个整数。如果到达流......
  • springboot 整合 mybatis-plus
    在创建springboot模块时,依赖勾选时没有mybaits-plus选项,原因是其未被加入。所以必须要手动引入依赖<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</vers......
  • mysql 8.0数据类型 json
    mysql8.0新增数据类型json。5.7通过blob等类型来保存json格式的数据,为什么还要专门增加这一数据格式的支持呢?  1.保证了JSON数据类型的强校验:JSON数据列会自动校验存入此列的内容是否符合JSON格式,    非正常格式则报错,而varchar类型和text等类型本身是不存在这......