【MyBatis_01】MyBatis和MyBatisPlus对枚举类型的处理

之前写过一篇Spring Data Jpa对于枚举类型的处理的文章,为了自己的小强迫症,就顺手写一下Mybatis/MyBatisPlus框架对枚举了类型的处理。

本文主要有以下内容:

  • MyBatis对枚举类型的处理
  • MyBatisPlus对枚举类型的处理

前置条件:请正确搭建Spring Boot项目工程并引入相关的依赖。

MyBatis对枚举类型的处理

MyBatis对枚举类型的处理比MyBatisPlus的处理要复杂一些,因此我们弄明白MyBatis是如何处理枚举类型的。

定义枚举类

我们以常见的性别举例,定义如下的枚举类型。

java 复制代码
public enum UserGenderEnum {
​
    FEMALE(0, "女"),
    MALE(1, "男");
​
​
    private Integer code;
    private String desc;
​
    public static UserGenderEnum convert(Integer code) {
        if (code == null) {
            return null;
        }
        return Stream.of(values())
                .filter(bean -> bean.code.equals(code))
                .findAny()
                .orElse(null);
    }
​
    UserGenderEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
​
    public Integer getCode() {
        return code;
    }
​
    public String getDesc() {
        return desc;
    }
}

定义实体类

在枚举类定义完毕后,我们就需要在实体类中使用枚举类,建立枚举类和实体类的关系。

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDO {
​
    private Integer userId;
​
    private String userName;
​
    private String password;
​
    private UserGenderEnum gender;
}

此时假定有了一个新增insert.do接口和find_one.do接口,此时如果不做任何处理,直接调用将会分别出现服下错误:

新增的错误信息如下:

查询的错误如下:

直接使用是不行的,幸运的是MyBatis给我们提供了一个抽象类让我们实现就可以让错误消失,达到我们预期的效果。

实现自定义枚举Handle

MyBatis中,提供了一个抽象父类BaseTypeHandler用于处理对枚举类型的转换。实现如下:

java 复制代码
@Slf4j
public class UserGenderHandler extends BaseTypeHandler<UserGenderEnum> {
​
    // 存调用 
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, UserGenderEnum parameter, JdbcType jdbcType) throws SQLException {
        log.info("i = {},parameter ={}",i,parameter);
        // 存的值就是枚举对象对应的code
        ps.setInt(i,parameter.getCode());
    }
​
    // 通过字段查询的时候调用 将db中存的code 转换为对应的枚举对象
    @Override
    public UserGenderEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Integer code = rs.getInt(columnName);
        log.info("columnName = {}",columnName);
        return UserGenderEnum.convert(code);
    }
​
    // 通过字段索引时调用
    @Override
    public UserGenderEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int code = rs.getInt(columnIndex);
        log.info("columnIndex: code = {} " ,code);
        return UserGenderEnum.convert(code);
    }
​
    // 通过存储过程时调用
    @Override
    public UserGenderEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int code = cs.getInt(columnIndex);
        log.info("CallableStatement columnIndex: code = {} " ,code);
        return UserGenderEnum.convert(code);
    }
}

在写完自定Handler之后,我们只需要在application.yml中添加如下配置即可

yml 复制代码
server:
  port: 8888
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_tutorial?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath:/mapper/*.xml
  # 新添枚举类型的处理。
  type-handlers-package: com.mybatis.tutorial.enums.handler
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true

完成上述配置之后,就可以正常使用了。xml和对应的controller代码如下:

controller中的代码:

java 复制代码
 @Resource
    UserServiceInt userService;
​
    @PostMapping("insert.do")
    public UserDO insert(@RequestBody UserDO userDO){
​
        log.info("user = {}",userDO);
        return userService.insertUser(userDO);
    }
​
    @GetMapping("find_one.do")
    public UserDO findUserById(Integer userId){
        return userService.findUserByUserId(userId);
    }
​

Mapper.xml代码如下:

java 复制代码
0<select id="findUserByUserId" parameterType="integer" resultType="com.mybatis.tutorial.domain.UserDO">
    select * from user where user_id = #{userId}
</select>
​
<insert id="insertUser" parameterType="com.mybatis.tutorial.domain.UserDO" useGeneratedKeys="true" keyProperty="userId">
    insert into user(user_name,gender,password) values (#{userName},#{gender},#{password})
</insert>

这就是MyBatis对枚举类型的处理。

MyBatisPlus对枚举类型的处理

MyBatisPlus中对枚举类型的处理很简单只需要使用两个注解即可:

  • @EnumValue:用于标注数据库要存的枚举属性
  • @jsonValue:将数据库存的对象转换为枚举对象之后的序列化的值。

示例代码如下:

java 复制代码
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum GenderEnum {
​
    FEMALE(0,"女"),
    MALE(1,"男");
​
    @EnumValue
    private Integer code;
​
    // 如果不使用此注解 则json对象为FEMALE / MALE
    // 使用此注解后 则为 女 / 男
    @JsonValue
    private String desc;
​
}

使用@JsonValue的情况:

不使用的情况如下:

不需要写额外的handler和配置简单易用!如果按照上面的步骤出现异常,则将版本更新到最新版即可!

相关推荐
砍材农夫几秒前
物联网实战:Spring Boot MQTT | MQTT 设备模拟器演示(附源码)
java·spring boot·后端·物联网·spring·netty
我叫黑大帅16 分钟前
解决聊天页内部滚轮改为页面滚动问题
javascript·后端·面试
TDengine (老段)21 分钟前
TDengine 压缩编码机制 — 双层压缩架构与类型特化算法
大数据·数据库·物联网·算法·时序数据库·tdengine·涛思数据
IT_陈寒1 小时前
Python的线程池居然把我坑在了垃圾回收这块
前端·人工智能·后端
苏渡苇2 小时前
Redis 持久化——RDB 快照 vs AOF 日志
数据库·redis·缓存·redis持久化·aof vs rdb
zhangxingchao2 小时前
AI应用开发八:RAG相关技术总结
前端·人工智能·后端
吴佳浩2 小时前
Go史上最大“打脸”现场来了:泛型方法终于实现了
后端·go
Huyuejia2 小时前
runtime-ask
后端
Rust研习社2 小时前
90% 的 Rust 新手都不知道的 3 个实用开发技巧
后端·rust·编程语言
l1t2 小时前
DeepSeek总结的使用 PEG 实现运行时可扩展的 SQL 解析器
数据库·sql