当前位置:   article > 正文

springboot+mybatis对枚举类型的处理-自定义类型处理器_springboot+mybatis 自定义类型处理器配置无效问题

springboot+mybatis 自定义类型处理器配置无效问题

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

  上篇springboot+mybatis中对枚举类型参数的处理EnumOrdinalTypeHandler与EnumTypeHandler区别我们测试了下EnumTypeHandler和EnumOrdinalTypeHandler的使用,假如有一个枚举类STUDENT("a","学生"),TEACHER("b","教师");  我们存的是实例名STUDENT/TEACHER,或者ordinal值0/1,但是我们希望数据库中存储code值,也就是a或者b,那就需要通过自定义类型处理器来实现。

自定义处理器的写法可以参考EnumOrdinalTypeHandler或者EnumTypeHandler的源码。

看一下EnumOrdinalTypeHandler的源码:

  1. EnumOrdinalTypeHandler使用了泛型,自定义的这个处理器只是处理PersonType类,
  2. EnumOrdinalTypeHandler的setNonNullParameter方法:因为EnumOrdinalTypeHandler存储到数据库中的是ordinal值,所以它用的是setInt,自定义的希望存储a/b到数据库,改为setString就好了

  3. EnumOrdinalTypeHandler的getNullableResult方法:上篇提到EnumOrdinalTypeHandler使用枚举实例的ordinal值(从0开始)来和枚举类之间做转换,可以看到方法中通过rs.getInt(columnName)得到数据库列中的值,即枚举的ordinal值,最终返回enums[i],看下这个enums[]是个啥,            

    自定义的时候我们数据库中存储的是a/b,自然根据列名获取值就应改为String i = rs.getString(columnName),在返回的时候很显然没法直接通过列值直接获取enums[]数组中的值,因此这一块需要修改下。

贴一下自定义的一个处理器:

  1. package com.example.springbootmybatis.config;
  2. import com.example.springbootmybatis.enums.PersonType;
  3. import java.sql.CallableStatement;
  4. import java.sql.PreparedStatement;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. import org.apache.ibatis.type.BaseTypeHandler;
  8. import org.apache.ibatis.type.JdbcType;
  9. public class PersonTypeHandler extends BaseTypeHandler<PersonType> {
  10. private Class<PersonType> type;
  11. private PersonType[] enums;
  12. public PersonTypeHandler(Class<PersonType> type) {
  13. if (type == null)
  14. throw new IllegalArgumentException("Type argument cannot be null");
  15. this.type = type;
  16. this.enums = type.getEnumConstants();
  17. if (this.enums == null)
  18. throw new IllegalArgumentException(type.getSimpleName()
  19. + " does not represent an enum type.");
  20. }
  21. /**
  22. * 定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型
  23. */
  24. @Override
  25. public void setNonNullParameter(PreparedStatement ps, int i, PersonType parameter,
  26. JdbcType jdbcType) throws SQLException {
  27. ps.setString(i, parameter.getCode());
  28. }
  29. /**
  30. * 定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型
  31. */
  32. @Override
  33. public PersonType getNullableResult(ResultSet rs, String columnName) throws SQLException {
  34. // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
  35. String i = rs.getString(columnName);
  36. if (rs.wasNull()) {
  37. return null;
  38. } else {
  39. // 根据数据库中的value值,定位PersonType子类
  40. return PersonType.getEnum(i);
  41. }
  42. }
  43. /**
  44. * 定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型
  45. */
  46. @Override
  47. public PersonType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
  48. return null;
  49. }
  50. /**
  51. * 定义调用存储过程后,如何把数据库类型转换为对应的Java类型
  52. */
  53. @Override
  54. public PersonType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
  55. return null;
  56. }
  57. }

如上:通过我们对源码的分析,没办法直接根据列值(a/b)从enums[]中直接获取我们想要枚举,可以考虑将枚举转为map,map的key为数据库保存的值(a/b),map的value为枚举值,所以在取值的时候直接通过key取值就可以,return PersonType.getEnum(i);

贴一下转map的代码,直接写到Person类中了,当然你也可以单独写一个工具类,

  1. package com.example.springbootmybatis.enums;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public enum PersonType {
  5. STUDENT("a","学生"),
  6. TEACHER("b","教师");
  7. private String code;
  8. private String text;
  9. PersonType(String code,String text) {
  10. this.code=code;
  11. this.text=text;
  12. }
  13. public String getCode() {
  14. return code;
  15. }
  16. public void setCode(String code) {
  17. this.code = code;
  18. }
  19. public String getText() {
  20. return text;
  21. }
  22. public void setText(String text) {
  23. this.text = text;
  24. }
  25. static Map<String, PersonType> enumMap = new HashMap<String, PersonType>();
  26. static {
  27. for (PersonType type : PersonType.values()) {
  28. enumMap.put(type.getCode(), type);
  29. }
  30. System.out.println(enumMap);
  31. }
  32. public static PersonType getEnum(String code) {
  33. return enumMap.get(code);
  34. }
  35. }

最后别忘了在配置文件中配置一下自定义的处理器:

  1. <typeHandlers>
  2. <!--<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
  3. javaType="com.example.springbootmybatis.enums.PersonType" />-->
  4. <typeHandler handler="com.example.springbootmybatis.config.PersonTypeHandler"
  5. javaType="com.example.springbootmybatis.enums.PersonType" />
  6. </typeHandlers>

测试下,插入四条数据:

看下数据库中:

测试下查询:

一切正常,但是考虑一下如果我们有很多枚举,这样转换的话,那我们需要为每一个枚举定义一个Handler,然后在mybatis配置文件中添加多个typeHandler。其实不必这样,我们可以参考EnumOrdinalTypeHandler源码的写法使用泛型定义成一个通用的枚举转换处理器,有时间再补充。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/173070?site
推荐阅读
相关标签
  

闽ICP备14008679号