目錄
一、測試使用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