MyBatis-Plus使⽤枚举⾃动关联注⼊实体参数数据
什么是枚举⾃动注⼊?
官⽅⽂档是这么解释的
解决了繁琐的配置,让 mybatis 优雅的使⽤枚举属性!
按我的理解是维护在内存中且不易修改的轻量级字典。⽬前觉得这个功能的使⽤场景相对有限,但是如果有⽤到的话开箱即⽤也是很棒的。废话不多说,接下来让我们看⼀下它的实际效果吧。
实际效果
通常情况下,我们会这样声明⼀个⽤户实体
public class User {
private String id;
private String name;
private Integer age;
private String phone;
//省略getter&setter&constructor
…
fastjson怎么用}
那么最终获取到的JSON数据应该类似于这样
{
id: “1”,
name: “张三”,
age: 18,
phone: “10000”
}
如若使⽤MyBatis-Plus的枚举⾃动关联注⼊,可以更优雅的实现如下效果
{
id: “1”,
name: “张三”,
age: “⼗⼋岁”,
phone: “中国电信”
}
实现步骤
实现过程仅有三步且⾮常简单,代码量也⾮常的少,下⾯介绍⼀下实现步骤。
1.创建两个枚举对象,分别为AgeEnum与PhoneEnum,这⾥使⽤枚举建⽴⼀个映射关系。
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", "中国联通"),
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了,否则⾃动关联注⼊的是枚举名(name属性),如下所⽰别忘记实现IEnum接⼝,否则⾃动关联注⼊的是枚举名(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的枚举⾃动关联注⼊就完成了。
踩坑
在使⽤枚举⾃动关联注⼊时,还踩了⼀个坑。在代码正确的情况下出现了如下问题。
{
id: null,
name: null,
age: null,
phone: null
}
查出的所有值都为null,通过DEBUG跟踪代码发现问题。数据库中将实体中的某个枚举属性设置为了tin
yint类型,在数据库中存储的值是1,枚举中也是使⽤1来映射关系,然⽽MyBaits-Plus在获取值是却读成了true,因此枚举并没有映射成功,返回null值。
当获取IsEnableEnum的枚举时,会执⾏这⾏代码获取枚举中的关系映射
EnumUtils.pe, rs.getObject(columnName));
但是MyBatis读取到的值变成了true
⽆法正确匹配到映射的值,返回null值,IsEnableEnum中声明的映射关系如下。
ENABLE(1, “可⽤”), LIMIT(-1, “禁⽤”);
解决⽅法
1.将表中IsEnableEnum枚举对应的字段is_enable类型由tinyint改为int即可,这种解决⽅法的优点就是不⽤修改代码就解决问题。
2.MySQL中tinyint(1)对应Java中的boolean类型,⾮0为true,0为false。因此修改IsEnableEnum中的映射关系,如下。
ENABLE(true, “可⽤”), LIMIT(false, “禁⽤”);
参数解析
当使⽤枚举注⼊的⽅式时,作为参数解析如果不注意会出现解析异常的情况。这⾥以修改User的is_enable值(数据库表中字段属性设置为int)为例看下具体解析异常情况的问题。例如,我们需要通过下⾯这个接⼝接收JSON请求参数来修改⽤户的信息。
@PostMapping
public User saveUser(@RequestBody User user) {
return userService.insertOrUpdate(user) ? userService.Id()) : null;
}
使⽤Postman模拟请求,JSON参数
{
"id":"922000984245391362",
"isEnable":-1
}
响应结果
{
"timestamp": "2018-05-12T04:20:15.920+0000",
"status": 400,
"error": "Bad Request",
"exception": "org.verter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not deserialize value of type com.ums.IsEnableEnum from number -1: index value outsid e legal index range [0..1]; nested exception is com.fasterxml.InvalidFormatException: Can not deserialize value of type ums.IsEnableEnum from number -1: index value outside legal index range [0..1]\n at [Source: java.io.PushbackInputStream@25386a8e; l ine: 3, column: 13] (through reference chain: com.githubmon.domain.User[\"isEnable\"])",
"path": "/"
}
从错误信息我们可知,⽆法将-1映射成IsEnableEnum枚举,可⽤范围是0…1,那么应该怎么解决呢?
⾃⼰摸索出的解决⽅式有两种,分别为
使⽤value属性映射,经过测试0对应的是ENABLE(1, “可⽤”),1对应的是LIMIT(-1, “禁⽤”)。很奇葩吧,因此不推荐此⽅式。
使⽤desc属性映射,将JSON请求参数改成如下就可以解析成功不报错。
{
"id":"922000984245391362",
"isEnable":"禁⽤"
}
总结
MyBatis-Plus这个特性⽬前⽤的还是不多,本质上其实还是把映射关系写死在代码中且个⼈觉得设计有些许不合理的地⽅,并不能替代字典,因此还是推荐使⽤字典⽅式,可以动态的修改映射关系。当项⽬遇到希望使⽤⽐字典更轻更快更容易上⼿的场景时,可以尝试使⽤枚举注⼊的⽅式。
针对于解决⽅法的选择个⼈想法是,当存储的值仅有两个且关系相对时,可以使⽤⽅法⼆,⽽在任何场景下⽅法⼀都适⽤,因此个⼈⽐较推荐⽅法⼀,因为可以存储更多的值和映射关系,例如上⽂的电话号码枚举。
最后,贴上MyBatis-Plus的官⽅⽂档,强烈推荐⼩伙伴们去尝试使⽤,⾮常棒的⼀个开源项⽬。
容易出错的⼏个点
1.前台传值类型与后台枚举参数类型不符
<⽅法未添加@JsonValue注解
3.int类型get⽅法类型使⽤
public Serializable getValue(){
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论