Mybatis讀取和存儲(chǔ)json類(lèi)型數(shù)據(jù)的實(shí)現(xiàn)
不管數(shù)據(jù)庫(kù)當(dāng)中是以json還是longtext數(shù)據(jù)類(lèi)型來(lái)存json,都可以在mybatis當(dāng)中使用string來(lái)接數(shù)據(jù)。這一點(diǎn)毋庸置疑!但是想要使用JSONObject類(lèi)型的字段來(lái)取值是否可以呢?
一、測(cè)試使用JSONObject來(lái)獲取json

接下來(lái)我們來(lái)測(cè)試一下,我用的是mybatis-plus框架,mybatis-plus和mybatis是一樣的,無(wú)非就是mybatis-plus封裝好了一些crud方法。但是對(duì)于手寫(xiě)xml來(lái)說(shuō)兩個(gè)框架是一樣的。

實(shí)體類(lèi)如下:這里的JSONObject我用的hutool工具包的,JSONObject一般引用的json框架都有

測(cè)試接口如下:這里一共寫(xiě)了兩個(gè)接口,一個(gè)接口是手寫(xiě)的,一個(gè)是調(diào)用的mybatis-plus當(dāng)中提供的BaseMapper的selectList方法



查詢結(jié)果如下:假如想要使用JSONObject來(lái)映射數(shù)據(jù)庫(kù)當(dāng)中的json數(shù)據(jù),不做任何配置是取不到的。

這個(gè)是訪問(wèn)mybatis-plus當(dāng)中提供的查詢方法

得出結(jié)論:在不做任何配置的情況下,不管是手寫(xiě)的xml接口還是用mybatis-plus自帶的查詢接口,都是無(wú)法將json數(shù)據(jù)映射到JSONObject類(lèi)型的字段當(dāng)中的。
二、設(shè)置@TableName的autoResultMap為true,@TableField的typeHandler為JacksonTypeHandler.class

兩個(gè)接口測(cè)試如下:調(diào)整過(guò)后,mybatis-plus當(dāng)中自帶的接口是可以將json數(shù)據(jù)映射到JSONObject類(lèi)型的字段當(dāng)中的(不管是longtext類(lèi)型存儲(chǔ)的json還是json類(lèi)型存儲(chǔ)的json數(shù)據(jù))


對(duì)于mybatis-plus框架我們將@TableName的autoResultMap為true,然后@TableField的typeHandler為JacksonTypeHandler.class之后,調(diào)用mybatis-plus自帶的查詢接口是可以將json數(shù)據(jù)映射到JSONObject類(lèi)型的字段當(dāng)中的。
注意:如果@TableName的autoResultMap不設(shè)置為true,那么設(shè)置typeHandler不會(huì)生效
三、設(shè)置xml當(dāng)中的resultMap
使用mybatis,有兩個(gè)屬性標(biāo)簽<resultType>、<resultMap>可以提供結(jié)果映射。
雖然resultType 屬性在大部分情況下都?jí)蛴?,但是在一些特殊情況下無(wú)能為力,比如屬性名和列名不一致,為一些連接的復(fù)雜語(yǔ)句編寫(xiě)映射代碼。遇到這些情況,我們要使用<resultMap>標(biāo)簽,一份 <resultMap> 能夠代替實(shí)現(xiàn)同等功能的數(shù)千行代碼。
resultMap 元素是 MyBatis 中最重要最強(qiáng)大的元素。resultMap 的設(shè)計(jì)思想是,對(duì)簡(jiǎn)單的語(yǔ)句做到零配置,對(duì)于復(fù)雜一點(diǎn)的語(yǔ)句,只需要描述語(yǔ)句之間的關(guān)系就行了。
注意:這里去掉了
<reslutType>屬性,用<resultMap>代替,二者只能選擇其中的一個(gè)。
其實(shí)在上面設(shè)置@TableName的autoResultMap為true,@TableField的typeHandler為JacksonTypeHandler.class等同于在xml當(dāng)中配置resultMap的某個(gè)屬性使用JacksonTypeHandler。只不過(guò)mybatis-plus這塊使用的是注解的形式,而mybatis應(yīng)該是沒(méi)有注解方式的。所以他只能用以下方式:
<?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>查詢結(jié)果如下:

四、JacksonTypeHandler講解
JacksonTypeHandler是mybatis-plus提供的,不管是使用注解方式還是使用xml方式當(dāng)中都使用到了JacksonTypeHandler類(lèi)。那么這個(gè)類(lèi)到低是干什么的?假如我使用的是mybatis而并不是mybatis-plus該怎么辦?
JacksonTypeHandler就是專(zhuān)門(mén)用來(lái)做數(shù)據(jù)映射轉(zhuǎn)換的。是mybatis-plus的,但是實(shí)際上繼承的是BaseTypeHandler,而B(niǎo)aseTypeHandler是mybatis的,那么我們也就可以基于BaseTypeHandler來(lái)自己寫(xiě)一個(gè)。
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 {
// 核心轉(zhuǎn)換,將數(shù)據(jù)庫(kù)讀取的字符串,轉(zhuǎn)換為指定的class類(lèi)型
return (T) mapper.readValue(content, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
return null;
}
}
}五、新增假如是JSONObject異常問(wèn)題
而對(duì)于 typeHandler 屬性,MyBatis 只支持寫(xiě)在 2 個(gè)地方:
定義在 resultMap 里,作用于查詢結(jié)果的封裝
定義在 insert 和 update 語(yǔ)句的 #{property} 中的 property后面
(例:#{property,typehandler=xxx.xxx.xxx}),并且只作用于當(dāng)前 設(shè)置值
假如不配置是會(huì)報(bào)錯(cuò)的!

六、遇到轉(zhuǎn)義的問(wèn)題

在使用JSONObject作為Java對(duì)象的類(lèi)型存值和取值是可以原樣返回的:

那假如是使用的String存值和取值會(huì)發(fā)生什么樣的場(chǎng)景呢?
首先使用String來(lái)直接接json對(duì)象肯定是不可以的,直接會(huì)報(bào)400異常。


針對(duì)于這個(gè)問(wèn)題有兩種方案,一種是對(duì)json建立Java對(duì)象,還有一種是直接使用JSONObject


假如使用字符串來(lái)查詢會(huì)出現(xiàn)轉(zhuǎn)義的問(wèn)題

遇到這個(gè)問(wèn)題可以使用commons-lang3包下的StringEscapeUtils.unescapeJava進(jìn)行轉(zhuǎn)換一下

查詢結(jié)果如下:

到此這篇關(guān)于Mybatis讀取和存儲(chǔ)json類(lèi)型數(shù)據(jù)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Mybatis讀取和存儲(chǔ)json內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解JVM 運(yùn)行時(shí)內(nèi)存使用情況監(jiān)控
這篇文章主要介紹了詳解JVM 運(yùn)行時(shí)內(nèi)存使用情況監(jiān)控,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Jenkins環(huán)境搭建實(shí)現(xiàn)過(guò)程圖解
這篇文章主要介紹了Jenkins環(huán)境搭建實(shí)現(xiàn)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Java實(shí)現(xiàn)字符串與字節(jié)數(shù)組之間相互轉(zhuǎn)換
在Java編程中,字符串(String)和字節(jié)數(shù)組(byte[])之間的相互轉(zhuǎn)換是非常常見(jiàn)的操作,這種轉(zhuǎn)換在網(wǎng)絡(luò)編程、文件處理、加密解密等場(chǎng)景中尤為重要,本文將詳細(xì)介紹如何在Java中實(shí)現(xiàn)字符串與字節(jié)數(shù)組之間的相互轉(zhuǎn)換,需要的朋友可以參考下2025-02-02
java 單元測(cè)試 對(duì)h2數(shù)據(jù)庫(kù)數(shù)據(jù)清理方式
這篇文章主要介紹了java 單元測(cè)試 對(duì)h2數(shù)據(jù)庫(kù)數(shù)據(jù)清理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
java 反射調(diào)用Service導(dǎo)致Spring注入Dao失效的解決方案
這篇文章主要介紹了java 反射調(diào)用Service導(dǎo)致Spring注入Dao失效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
java jackson 將對(duì)象轉(zhuǎn)json時(shí),忽略子對(duì)象的某個(gè)屬性操作
這篇文章主要介紹了java jackson 將對(duì)象轉(zhuǎn)json時(shí),忽略子對(duì)象的某個(gè)屬性操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
在 Spring Boot 中使用 @Autowired和 @Bean
本文通過(guò)一個(gè)示例演示了如何在SpringBoot中使用@Autowired和@Bean注解進(jìn)行依賴(lài)注入和Bean管理,示例中定義了一個(gè)Student類(lèi),并通過(guò)配置類(lèi)TestConfig初始化Student對(duì)象,在測(cè)試類(lèi)中,通過(guò)@Autowired注解自動(dòng)注入Student對(duì)象并輸出其屬性值,感興趣的朋友跟隨小編一起看看吧2025-02-02

