简介方案对比
本处列举表示类型或状态的常用方法的对比。
法1:使用数字表示(不推荐)
//1:支付宝支付;2:微信支付;3:银行卡支付 private Integer payType;
这种方法的缺点:可读性极差,排查问题也麻烦。比如:前端页面上看到了2这个类型,还要看接口文档或者问后端这是什么意思,浪费时间!
法2:使用字符串表示(不推荐)
//ALIPAY:支付宝;WECHAT_PAY:微信;BANK_CARD_PAY:银行卡支付 private String payType;
这种方式比法1好一些了,提高了数据库的可读性和排查问题速度。
缺点:难以控制不允许数据库的pay_type为空字符串这种情况;支持的类型没有限制死,前端传个其他的字符串也能存入数据库。
法3:使用枚举表示(推荐)
枚举是这种场景最好的方案(枚举本身就是为了表示可穷举类型而发明出来的!)。
定义一个枚举类
package com.example.demo.order.enums; import lombok.Getter; @Getter public enum PayTypeEnum { ALIPAY("支付宝"), WECHAT_PAY("微信支付"), BANK_CARD_PAY("银行卡支付"), ; private final String description; PayTypeEnum(String description) { this.description = description; } }
Entity中定义枚举类型字段
private PayTypeEnum payType;
优点
- 可读性极高,排查问题很快(比如:前端页面上看到ALIPAY这个类型,一眼就能知道是支付宝)
- 可以控制不允许数据库的pay_type为空字符串这种情况(因为枚举字段不可能有空字符串)
- 支持的类型限制死,前端传个其他的字符串无法存入数据库。
枚举用法示例
建表
CREATE TABLE `t_order` ( `id` bigint NOT NULL COMMENT 'ID', `order_no` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '订单号', `pay_type` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '支付类型。ALIPAY:支付宝;WECHAT_PAY:微信;BANK_CARD_PAY:银行卡支付。', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单';
pay_type字段加了NOT NULL限制。
Entity
package com.example.demo.order.entity; import com.baomidou.mybatisplus.annotation.TableName; import com.example.demo.order.enums.PayTypeEnum; import lombok.Data; @Data @TableName("t_order") public class Order { private Long id; private String orderNo; private PayTypeEnum payType; }
Enum
package com.example.demo.order.enums; import lombok.Getter; @Getter public enum PayTypeEnum { ALIPAY("支付宝"), WECHAT_PAY("微信支付"), BANK_CARD_PAY("银行卡支付"), ; private final String description; PayTypeEnum(String description) { this.description = description; } }
Controller
package com.example.demo.order.controller; import com.example.demo.order.entity.Order; import com.example.demo.order.service.OrderService; import com.example.demo.user.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @PostMapping("pay") public void pay(@RequestBody Order order) { orderService.save(order); } }
Service
接口
package com.example.demo.order.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.demo.order.entity.Order; public interface OrderService extends IService { }
实现
package com.example.demo.order.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.order.entity.Order; import com.example.demo.order.mapper.OrderMapper; import com.example.demo.order.service.OrderService; import org.springframework.stereotype.Service; @Service public class OrderServiceImpl extends ServiceImpl implements OrderService { }
Mapper
package com.example.demo.order.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo.order.entity.Order; import org.springframework.stereotype.Repository; @Repository public interface OrderMapper extends BaseMapper { }
测试
1.正常操作
写入成功,枚举的name()方法的值会写到数据库。
后端结果
数据库结果
2.前端传空字符串
此时会报错,因为枚举中没有对应空字符串的。
后端结果(无法将空字符串反序列化为枚举对象)
2022-09-10 10:14:30.406 WARN 128760 — [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `com.example.demo.order.enums.PayTypeEnum` from String “”: not one of the values accepted for Enum class: [ALIPAY, BANK_CARD_PAY, WECHAT_PAY]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.example.demo.order.enums.PayTypeEnum` from String “”: not one of the values accepted for Enum class: [ALIPAY, BANK_CARD_PAY, WECHAT_PAY]
at [Source: (PushbackInputStream); line: 4, column: 16] (through reference chain: com.example.demo.order.entity.Order[“payType”])]
数据库结果(没写入数据)
3.前端传null
后端结果(pay_type为null,写入数据库时报错)
2022-09-10 10:24:20.514 ERROR 128760 — [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException:
### Error updating database. Cause: java.sql.SQLException: Field ‘pay_type’ doesn’t have a default value
### The error may exist in com/example/demo/order/mapper/OrderMapper.java (best guess)
### The error may involve com.example.demo.order.mapper.OrderMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO t_order ( id, order_no ) VALUES ( ?, ? )
### Cause: java.sql.SQLException: Field ‘pay_type’ doesn’t have a default value
; Field ‘pay_type’ doesn’t have a default value; nested exception is java.sql.SQLException: Field ‘pay_type’ doesn’t have a default value] with root cause
java.sql.SQLException: Field ‘pay_type’ doesn’t have a default value
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.25.jar:8.0.25]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.25.jar:8.0.25]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.25.jar:8.0.25]
at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:370) ~[mysql-connector-java-8.0.25.jar:8.0.25]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44) ~[HikariCP-3.4.5.jar:na]
……
数据库结果(没写入数据)
到此这篇关于SpringBoot Entity中枚举类型详细使用介绍的文章就介绍到这了,更多相关SpringBoot Entity内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!