2.5 通用枚举配置
相信后端的同学都经历过一个情况,比如性别
这个字段,分别值和名称对应1男
、2女
,这个字段在数据库时是数值类型,而前端展示则是展示字符串的名称。有几种常见实现方案呢?
- 数据库查询 sql 通过 case 判断,返回名称,以前 oracle 经常这么做
- 数据库返回的值,重新遍历赋值进去,这时候还需要判断这个值到底是男是女。
- 前端写死,返回 1 就是男,返回 2 就是女。
相信无论哪种方法都有其缺点,所以我们可以使用 mybatis-plus 提供的方式。我们在返回给前端时:
- 只需要在遍历时 get 这个枚举,直接赋值其名称,不需要再次判断。
- 直接返回给前端,让前端去去枚举的 name
这样大家都不需要写死这个值。
下面看看如何实现这个功能:
- 兴义枚举,实现 IEnum 接口:
import com.baomidou.mybatisplus.annotation.IEnum; import com.fasterxml.jackson.annotation.JsonFormat; /** * @description: 性别枚举 * @author:weirx * @date:2022/1/17 16:26 * @version:3.0 */ @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum SexEnum implements IEnum<Integer> { MAN(1, \"男\"), WOMAN(2, \"女\"); private Integer code; private String name; SexEnum(Integer code, String name) { this.code = code; this.name = name; } @Override public Integer getValue() { return code; } public String getName() { return name; } }
@JsonFormat 注解为了解决枚举类返回前端只展示构造器名称的问题。
- 实体类性别字段
@TableName(value = \"user\") public class UserDO { /** * 主键 */ @TableId(value = \"id\", type = IdType.AUTO) private Long id; /** * 昵称 */ @TableField(value = \"nickname\",condition = SqlCondition.EQUAL) private String nickname; /** * 性别 */ @TableField(value = \"sex\") private SexEnum sex; /** * 版本 */ @TableField(value = \"version\",update = \"%s+1\") private Integer version; /** * 时间字段,自动添加 */ @TableField(value = \"create_time\",fill = FieldFill.INSERT) private LocalDateTime createTime; }
- 配置文件扫描枚举
mybatis-plus: # 支持统配符 * 或者 ; 分割 typeEnumsPackage: com.wjbgn.*.enums
- 定义配置文件
@Bean public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() { return properties -> { GlobalConfig globalConfig = properties.getGlobalConfig(); globalConfig.setBanner(false); MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class); properties.setConfiguration(configuration); }; }
- 序列化枚举值为数据库值
以下我是使用的 fastjson:
- 全局(添加在前面的配置文件中):
@Bean public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() { // 序列化枚举值为数据库存储值 FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString); return properties -> { GlobalConfig globalConfig = properties.getGlobalConfig(); globalConfig.setBanner(false); MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class); properties.setConfiguration(configuration); }; }
- 局部
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString) private SexEnum sex;
2.6 自动填充
还记得前面提到的实体类当中的注解@TableFeild
吗?当中有个属性叫做 fill,通过FieldFill
设置属性,这个就是做自动填充用的。
public enum FieldFill { /** * 默认不处理 */ DEFAULT, /** * 插入填充字段 */ INSERT, /** * 更新填充字段 */ UPDATE, /** * 插入和更新填充字段 */ INSERT_UPDATE }
但是这个直接是不能使用的,需要通过实现 mybatis-plus 提供的接口,增加如下配置:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.time.LocalDateTime; /** * description: 启动自动填充功能 * @return: * @author: weirx * @time: 2022/1/17 17:00 */ @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { // 起始版本 3.3.0(推荐使用) this.strictInsertFill(metaObject, \"createTime\", LocalDateTime.class, LocalDateTime.now()); } @Override public void updateFill(MetaObject metaObject) { // 起始版本 3.3.0(推荐) this.strictUpdateFill(metaObject, \"updateTime\", LocalDateTime.class, LocalDateTime.now()); } }
字段如下:
/** * 时间字段,自动添加 */ @TableField(value = \"create_time\",fill = FieldFill.INSERT) private LocalDateTime createTime;
2.7 多数据源
前面提到过,配置文件当中配置了主从的方式,其实 mybatis-plus 还支持更多的方式:
- 多主多从
spring: datasource: dynamic: primary: master #设置默认的数据源或者数据源组,默认值即为master strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 datasource: master_1: master_2: slave_1: slave_2: slave_3:
- 多种数据库
spring: datasource: dynamic: primary: mysql #设置默认的数据源或者数据源组,默认值即为master strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 datasource: mysql: oracle: postgresql: h2: sqlserver:
- 混合配置
spring: datasource: dynamic: primary: master #设置默认的数据源或者数据源组,默认值即为master strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 datasource: master_1: slave_1: slave_2: oracle_1: oracle_2:
上面的三种方式,除了混合配置,我觉得都有肯能出现的吧。
- @DS 注解
可以注解在方法上或类上,同时存在就近原则 【方法上注解】 优先于 【类上注解】 :
@DS(\"slave_1\") public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements IUserService { @DS(\"salve_1\") @Override public List<UserDO> getList() { return this.getList(); } @DS(\"master\") @Override public int saveUser(UserDO userDO) { boolean save = this.save(userDO); if (save){ return 1; }else{ return 0; } } }
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
三、测试
经过上面的配置,下面开始进入测试验证阶段。
建立一张表:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nickname` varchar(255) NOT NULL COMMENT '昵称', `sex` tinyint(1) NOT NULL COMMENT '性别,1男2女', `create_time` datetime NOT NULL COMMENT '创建时间', `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 1是,0否', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8mb4;
controller:
/** * @description: 用户controller * @author:weirx * @date:2022/1/17 17:39 * @version:3.0 */ @RestController @RequestMapping(\"/user\") public class UserController { @Autowired private IUserService userService; /** * description: 新增 * @return: boolean * @author: weirx * @time: 2022/1/17 19:11 */ @RequestMapping(\"/save\") public boolean save() { UserDO userDO = new UserDO(); userDO.setNickname(\"大漂亮\"); userDO.setSex(SexEnum.MAN); return userService.save(userDO); } /** * description: 修改 * @param nickname * @param id * @return: boolean * @author: weirx * @time: 2022/1/17 19:11 */ @RequestMapping(\"/update\") public boolean update(@RequestParam String nickname,@RequestParam Long id) { UserDO userDO = new UserDO(); userDO.setNickname(nickname); userDO.setId(id); return userService.updateById(userDO); } /** * description: 删除 * @param id * @return: boolean * @author: weirx * @time: 2022/1/17 19:11 */ @RequestMapping(\"/delete\") public boolean delete(@RequestParam Long id) { UserDO userDO = new UserDO(); userDO.setId(id); return userService.removeById(userDO); } /** * description: 列表 * @return: java.util.List<com.wjbgn.user.entity.UserDO> * @author: weirx * @time: 2022/1/17 19:11 */ @RequestMapping(\"/list\") public List<UserDO> list() { return userService.list(); } /** * description: 分页列表 * @param current * @param size * @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page * @author: weirx * @time: 2022/1/17 19:11 */ @RequestMapping(\"/page\") public Page page(@RequestParam int current,@RequestParam int size) { return userService.page(new Page<>(current,size), new QueryWrapper(new UserDO())); } }
记过上面的接口验证,功能没有问题,集成成功。上文基本覆盖了 mybatis-plus 常用的特性,有同学说自动代码生成没说?本文项目代码 gitee 地址: https://gitee.com/wei_rong_xin/rob-necessities.git