MyBatis-Plus如何使用枚舉自動關(guān)聯(lián)注入詳解
什么是枚舉自動注入?
官方文檔是這么解釋的
解決了繁瑣的配置,讓 mybatis 優(yōu)雅的使用枚舉屬性!
按我的理解是維護在內(nèi)存中且不易修改的輕量級字典。目前覺得這個功能的使用場景相對有限,但是如果有用到的話開箱即用也是很棒的。廢話不多說,接下來讓我們看一下它的實際效果吧。
實際效果
通常情況下,我們會這樣聲明一個用戶實體
public class User {
????private String id;
private String name;
private Integer age;
private String phone;
????//省略getter&setter&constructor
????...
}那么最終獲取到的JSON數(shù)據(jù)應(yīng)該類似于這樣
{
id: "1",
name: "張三",
age: 18,
phone: "10000"
}如若使用MyBatis-Plus的枚舉自動關(guān)聯(lián)注入,可以更優(yōu)雅的實現(xiàn)如下效果
{
id: "1",
????????name: "張三",
age: "十八歲",
phone: "中國電信"
}實現(xiàn)步驟
實現(xiàn)過程僅有三步且非常簡單,代碼量也非常的少,下面介紹一下實現(xiàn)步驟。
1.創(chuàng)建兩個枚舉對象,分別為AgeEnum與PhoneEnum,這里使用枚舉建立一個映射關(guān)系。
public enum AgeEnum implements IEnum {
ONE(1, "一歲"),
TWO(2, "二歲");
private int age;
private String desc;
AgeEnum(final int age, final String desc) {
this.age = age;
this.desc = desc;
}
@Override
public Serializable getValue() {
return this.age;
}
@JsonValue
public String getDesc(){
return this.desc;
}
}public enum PhoneEnum implements IEnum {
CMCC("10086", "中國移動"),
CUCC("10010", "中國聯(lián)通"),
CT("10000", "中國電信");
private String phone;
private String desc;
PhoneEnum(final String phone, final String desc) {
this.phone = phone;
this.desc = desc;
}
@Override
public Serializable getValue() {
return this.phone;
}
@JsonValue
public String getDesc(){
return this.desc;
}
}注意:
- @JsonValue是使用JackSon解析時有效,若使用fastjson,請看官方文檔提供的解決方案
- 不要把@JsonValue打成@JsonView了,否則自動關(guān)聯(lián)注入的是枚舉名(name屬性),如下所示
- 別忘記實現(xiàn)IEnum接口,否則自動關(guān)聯(lián)注入的是枚舉名(name屬性),如下所示
{
id: "1",
????????name: "張三",
age: "十八歲",
phone: "CT"
}2.將User實體中的屬性替換為枚舉,例如
public class User {
????private String id;
private String name;
private AgeEnum age;
private PhoneEnum phone;
????//省略getter&setter&constructor
????...
}3.配置掃描枚舉,添加如下配置
mybatis-plus.typeEnumsPackage=com.xxx.xxx.enums//枚舉所在路徑
至此,使用MyBatis-Plus的枚舉自動關(guān)聯(lián)注入就完成了。
踩坑
在使用枚舉自動關(guān)聯(lián)注入時,還踩了一個坑。在代碼正確的情況下出現(xiàn)了如下問題。
{
id: null,
????????name: null,
age: null,
phone: null
}查出的所有值都為null,通過DEBUG跟蹤代碼發(fā)現(xiàn)問題。數(shù)據(jù)庫中將實體中的某個枚舉屬性設(shè)置為了tinyint類型,在數(shù)據(jù)庫中存儲的值是1,枚舉中也是使用1來映射關(guān)系,然而MyBaits-Plus在獲取值是卻讀成了true,因此枚舉并沒有映射成功,返回null值。

當(dāng)獲取IsEnableEnum的枚舉時,會執(zhí)行這行代碼獲取枚舉中的關(guān)系映射
EnumUtils.valueOf(this.type, rs.getObject(columnName));
但是MyBatis讀取到的值變成了true

無法正確匹配到映射的值,返回null值,IsEnableEnum中聲明的映射關(guān)系如下。
ENABLE(1, "可用"), LIMIT(-1, "禁用");
解決方法
1.將表中IsEnableEnum枚舉對應(yīng)的字段is_enable類型由tinyint改為int即可,這種解決方法的優(yōu)點就是不用修改代碼就解決問題。

2.MySQL中tinyint(1)對應(yīng)Java中的boolean類型,非0為true,0為false。因此修改IsEnableEnum中的映射關(guān)系,如下。
ENABLE(true, "可用"), LIMIT(false, "禁用");
參數(shù)解析
當(dāng)使用枚舉注入的方式時,作為參數(shù)解析如果不注意會出現(xiàn)解析異常的情況。這里以修改User的is_enable值(數(shù)據(jù)庫表中字段屬性設(shè)置為int)為例看下具體解析異常情況的問題。例如,我們需要通過下面這個接口接收JSON請求參數(shù)來修改用戶的信息。
@PostMapping
public User saveUser(@RequestBody User user) {
return userService.insertOrUpdate(user) ? userService.selectById(user.getId()) : null;
}使用Postman模擬請求,JSON參數(shù)
{
"id":"922000984245391362",
"isEnable":-1
}響應(yīng)結(jié)果
{
"timestamp": "2018-05-12T04:20:15.920+0000",
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not deserialize value of type com.github.common.domain.enums.IsEnableEnum from number -1: index value outside legal index range [0..1]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type com.github.common.domain.enums.IsEnableEnum from number -1: index value outside legal index range [0..1]\n at [Source: java.io.PushbackInputStream@25386a8e; line: 3, column: 13] (through reference chain: com.github.common.domain.User[\"isEnable\"])",
"path": "/"
}從錯誤信息我們可知,無法將-1映射成IsEnableEnum枚舉,可用范圍是0..1,那么應(yīng)該怎么解決呢?
自己摸索出的解決方式有兩種,分別為
- 使用value屬性映射,經(jīng)過測試0對應(yīng)的是ENABLE(1, "可用"),1對應(yīng)的是LIMIT(-1, "禁用")。很奇葩吧,因此不推薦此方式。
- 使用desc屬性映射,將JSON請求參數(shù)改成如下就可以解析成功不報錯。
{
"id":"922000984245391362",
"isEnable":"禁用"
}總結(jié)
MyBatis-Plus這個特性目前用的還是不多,本質(zhì)上其實還是把映射關(guān)系寫死在代碼中且個人覺得設(shè)計有些許不合理的地方,并不能替代字典,因此還是推薦使用字典方式,可以動態(tài)的修改映射關(guān)系。當(dāng)項目遇到希望使用比字典更輕更快更容易上手的場景時,可以嘗試使用枚舉注入的方式。
針對于解決方法的選擇個人想法是,當(dāng)存儲的值僅有兩個且關(guān)系相對時,可以使用方法二,而在任何場景下方法一都適用,因此個人比較推薦方法一,因為可以存儲更多的值和映射關(guān)系,例如上文的電話號碼枚舉。
最后,貼上MyBatis-Plus的官方文檔,強烈推薦小伙伴們?nèi)L試使用,非常棒的一個開源項目。
到此這篇關(guān)于MyBatis-Plus如何使用枚舉自動關(guān)聯(lián)注入的文章就介紹到這了,更多相關(guān)MyBatis-Plus枚舉自動關(guān)聯(lián)注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)獲取客戶端真實IP方法小結(jié)
本文給大家匯總介紹了2種使用java實現(xiàn)獲取客戶端真實IP的方法,主要用于獲取使用了代理訪問的來訪者的IP,有需要的小伙伴可以參考下。2016-03-03
IDEA創(chuàng)建Maven一直爆紅無法下載的問題解決辦法
這篇文章主要介紹了關(guān)于IDEA創(chuàng)建Maven一直爆紅無法下載的問題的解決辦法,文中圖文結(jié)合的方式給大家講解的非常詳細,對大家解決辦法非常有用,需要的朋友可以參考下2024-06-06
教你創(chuàng)建springcloud微服務(wù)的基礎(chǔ)子服務(wù)的超詳細過程
這篇文章主要介紹了創(chuàng)建springcloud微服務(wù)的基礎(chǔ)子服務(wù),主要是創(chuàng)建兩個springboot服務(wù),在教程中增加springcloud相關(guān)組件,本文分步驟給大家介紹的非常詳細,需要的朋友可以參考下2022-04-04
PageHelper插件實現(xiàn)一對多查詢時的分頁問題
這篇文章主要介紹了PageHelper插件實現(xiàn)一對多查詢時的分頁問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Java數(shù)據(jù)結(jié)構(gòu)之單鏈表的實現(xiàn)與面試題匯總
由于順序表的插入刪除操作需要移動大量的元素,影響了運行效率,因此引入了線性表的鏈?zhǔn)酱鎯Α獑捂湵?。本文為大家介紹了單鏈表的實現(xiàn)與面試題匯總,感興趣的可以了解一下2022-10-10
Java使用Thumbnailator實現(xiàn)圖片處理功能
Thumbnailator是一個簡單且功能強大的Java庫,用于生成縮略圖和執(zhí)行其他圖片處理任務(wù),在這篇博客中,我們將介紹如何使用Thumbnailator進行圖片的縮放、裁剪、旋轉(zhuǎn)等操作,需要的朋友可以參考下2024-07-07
Kotlin基礎(chǔ)教程之?dāng)?shù)據(jù)類型
這篇文章主要介紹了Kotlin基礎(chǔ)教程之?dāng)?shù)據(jù)類型的相關(guān)資料,需要的朋友可以參考下2017-05-05
在java中如何將inputStream對象轉(zhuǎn)換為File對象(不生成本地文件)
這篇文章主要介紹了在java中如何將inputStream對象轉(zhuǎn)換為File對象(不生成本地文件),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03

