MybatisPlus出現(xiàn)Error attempting to get column ‘xxx字段‘ from result set異常解決
MybatisPlus如何處理實體枚舉類型轉(zhuǎn)換的教程可以參考:點擊查看教程,本文重點分析使用@EnumValue注解轉(zhuǎn)換時遇到的一下錯誤原因,以及解決方案。
一、背景描述
在操作MybatisPlus的實體屬性一般都是基本類型或者對應的引用類型或者String類型。但是MySQL8早已支持enum枚舉類型,一直都沒有實際操作過,于是想著有個枚舉的場景打算實際項目里面用一下。當時在具體數(shù)據(jù)庫表中設計了一個字段state來表示狀態(tài),這個狀態(tài)有3個值:已入組、已出組、已移除。于是設計了這個字段為enum類型屬性。但是在具體查詢的時候出現(xiàn)如下的錯誤:

二、案例分析
當時具體場景比較簡單就兩個類:實體類、枚舉類
實體類(demo)
實體類的定義具體如下,重點關注屬性:state
@Data
@EqualsAndHashCode
@TableName("demo")
public class Demo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主鍵
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 身份證號
*/
@TableField("id_card")
private String idCard;
/**
* 受試者姓名
*/
@TableField("`name`")
private String name;
/**
* 聯(lián)系電話
*/
@TableField("phone")
private String phone;
/**
* 入組時間
*/
@TableField("join_time")
private Date joinTime;
/**
* 狀態(tài):已入組、已出組、已移除
*/
@TableField("state")
private DemoStateEnum state;
/**
* 最近一次操作的用戶
*/
@TableField("last_user")
private String lastUser;
/**
* 關聯(lián)項目ID
*/
@TableField("project_id")
private Integer projectId;
/**
* 最后一次操作時間
*/
@TableField("last_update")
private Date lastUpdate;
public static Demo builder(){
return new Demo();
}
}
枚舉類(DemoStateEnum)
public enum DemoStateEnum {
JOINED("已入組"),
OUTED("已出組"),
REMOVED("已移除");
/**
* 注意這個 @EnumValue注解一定要加上,否則SpringBoot啟動都會報錯,具體原因是因為MybatisePlus實現(xiàn)了根據(jù)這個注解表示實體屬性自動枚舉類型轉(zhuǎn)換。如果找不到就會報錯。
*/
@EnumValue
private String state;
DemoStateEnum(String state){
this.state = state;
}
/**
* @JSONField這個注解解決alibaba.fastjson序列化是枚舉顯示的索引的值,而我們想要的顯示是具體的值:已入組、已出組、已移除等。
*/
@JSONField
public String getState() {
return state;
}
@Override
public String toString() {
return "DemoStateEnum{" +
"state='" + state + '\'' +
'}';
}
}
表結(jié)構(gòu)
CREATE TABLE `demo` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`id_card` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '身份證號',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '受試者姓名',
`phone` varchar(13) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '聯(lián)系電話',
`join_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '入組時間',
`state` enum('已入組','已出組','已移除') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '狀態(tài):已入組、已出組、已移除',
`last_user` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最近一次操作的用戶',
`project_id` int NOT NULL COMMENT '關聯(lián)項目ID',
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次操作時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='枚舉測試表';
三、單元測試
@SpringBootTest
public class DemoTest {
@Autowired
private DemoMapper deemoMapper;
//查詢所有demo數(shù)據(jù)
@Test
public void querySubject() throws JsonProcessingException {
List<Demo> demos = deemoMapper.selectList(null);
System.err.println(JSON.toJSONString(demos));
}
}
執(zhí)行以上單元測試會出現(xiàn)上面的錯誤,這里我就再貼一下圖:

四、問題分析
# 根據(jù)上圖細看這句話 Caused by: java.sql.SQLFeatureNotSupportedException at com.alibaba.druid.pool.DruidPooledResultSet.getObject(DruidPooledResultSet.java:1771)
找到DruidPooledResultSet.getObject()這個方法打上一個斷點,然后根據(jù)idea的線程調(diào)用棧debug往上確定是由哪一步出現(xiàn)的異常。

如上圖設置好debug點,開始運行上面的單元測試方法querySubject方法,監(jiān)聽斷點:

那怎么知道上層是那個方法觸發(fā)了這個異常呢,接著看左邊的線程調(diào)用棧:可以看出黃色部分是上層真實異常的調(diào)用方。

基于以上我們繼續(xù)往下分析,可以發(fā)現(xiàn)MybatisEnumTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String)這個方法里面的ResultSet的具體參數(shù)類型是一個DruidPooledResultSet,然后再調(diào)用DruidPooledResultSet類中的getObject(String columnLabel, Class type)方法。
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
顯然這個方法無論誰調(diào)用都是會拋出SQLFeatureNotSupportedException異常,那這樣的話這個方法又有什么意義呢,于是猜想著是不是當前的druid是1.1.16(從下圖可以看出版本依賴)版本太低導致無法適配當前查詢場景,既然版本太低那就升級一下druid版本到1.1.21。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>

升級版本1.1.21繼續(xù)嘗試著運行,發(fā)現(xiàn)確實成功解決了。從下圖可以看出druid版本成功升級從黃色區(qū)域可以看出來,那為什么可以解決當前問題呢?于是嘗試進入同樣的DruidPooledResultSet類中的getObject(String columnLabel, Class type)方法。發(fā)現(xiàn)1.1.16版本中的固定異常SQLFeatureNotSupportedException沒有了,實現(xiàn)也完全不同了。如下:
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
try {
// 正常調(diào)用JDBC中的ResultSet了,所以可以正常獲取數(shù)據(jù),不再出現(xiàn)那個異常了。
return this.rs.getObject(columnLabel, type);
} catch (Throwable var4) {
throw this.checkException(var4);
}
}

查詢成功:

[{"id":4,"idCard":"666666","joinTime":"2023-08-09 15:21:13","lastUpdate":"2023-08-09 15:21:13","lastUser":"test user","name":"test name 6","phone":"123123123","projectId":2,"state":"已出組"},{"id":5,"idCard":"666666","joinTime":"2023-08-09 15:22:28","lastUpdate":"2023-08-09 15:22:28","lastUser":"test user","name":"test name 6","phone":"123123123","projectId":2,"state":"已出組"},{"id":6,"idCard":"666666","joinTime":"2023-08-09 15:24:00","lastUpdate":"2023-08-09 15:24:00","lastUser":"test user","name":"test name 6","phone":"123123123","projectId":2,"state":"已出組"}]
五、其他問題
alibaba.fastjson序列化枚舉時候顯示一個int值得問題,其實這個int值就是枚舉中的ordinary也就是枚舉列表中的索引。這個了解java枚舉的應該都清楚枚舉列表中的值都有自己對應的所有,而且底層也是存儲在一個數(shù)組中的,也就是相當于數(shù)組的下表。但是不希望在序列化的時候顯示這個下表,希望顯示state的值。如何解決,在枚舉的state屬性的get方法加上如下@JSONField注解,這樣就可以顯示state的枚舉值了。
@JSONField
public String getState() {
return state;
}到此這篇關于MybatisPlus出現(xiàn)Error attempting to get column ‘xxx字段‘ from result set異常解決的文章就介紹到這了,更多相關mybatis ‘xx‘ from result set內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- MyBatis異常java.sql.SQLSyntaxErrorException的問題解決
- Mybatis操作數(shù)據(jù)時出現(xiàn):java.sql.SQLSyntaxErrorException:?Unknown?column?'XXX'?in?'field?list'的問題解決
- MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法
- Mybatis配置錯誤:java.lang.ExceptionInInitializerError
- MybatisPlus BaseMapper 中的方法全部 Invalid bound statement (not found Error處理)
- 解決Mybatis出現(xiàn)報錯Error querying database.Cause: java.lang.IndexOutOfBoundsException: Index 9 out of
相關文章
Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境全過程
眾所周知Ubuntu是一種基于Linux的操作系統(tǒng),它提供了一個穩(wěn)定、安全和易于使用的環(huán)境,下面這篇文章主要給大家介紹了關于Linux?Ubuntu系統(tǒng)下配置JDK環(huán)境、MySQL環(huán)境的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-07-07
Java list與set中contains()方法效率案例詳解
這篇文章主要介紹了Java list與set中contains()方法效率案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08
java使用hadoop實現(xiàn)關聯(lián)商品統(tǒng)計
本篇文章java使用hadoop實現(xiàn)關聯(lián)商品統(tǒng)計,可以實現(xiàn)商品的關聯(lián)統(tǒng)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-10-10

