Mybatis-使用枚举或其它对象

1,518 阅读3分钟
  1. 需求分析:
    现在实体对象有一个 enabled 字段, 这个字段只有两个值, 分别为: 0 为禁用; 1 为启用. 我们希望在实体类中使用枚举类来避免手动验证 enabled 的值是否符合要求. 这里数据库的类型为 tinyint.

  2. 示例代码:

    /**
     * 枚举类
     */
    public enum EnabledEnum {
        disabled,
        enabled;
    }
    
    public Class User {
        private Integer id;
        private String username;
        private String userEmail;
        private Enabled enabled;
        
        // 省略其它代码
    }
    

    由于数据并不存在与 Enabled 枚举相对应的数据库类型, 因此在和数据库交互的时候不能直接使用枚举类型. Mybatis 是通过 TypeHandler 来处理 Java 类型和数据库类型的映射的. 在处理枚举类型时默认使用 org.apache.ibatis.type.EnumTypeHandler 处理器. 这个处理器会将枚举类型转化为字符串类型的字面量并使用.

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, parameter, JdbcType jdbcType) throws SQLException {
      if (jdbcType == null) {
        ps.setString(i, parameter.name());
      } else {
        // 这里获取枚举类型的名称作为参数值
        ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); 
      }
    }
    @Override
    public E getNullableResult(ResultSet rs, String columnName) throwSQLException {
      String s = rs.getString(columnName);
      // 这里根据枚举类型的名称获取对应的枚举对象
      return s == null ? null : Enum.valueOf(type, s);
    }
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throwSQLException {
      String s = rs.getString(columnIndex);
      // 这里根据枚举类型的名称获取对应的枚举对象
      return s == null ? null : Enum.valueOf(type, s);
    }
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndexthrows SQLException {
      String s = cs.getString(columnIndex);
      // 这里根据枚举类型的名称获取对应的枚举对象
      return s == null ? null : Enum.valueOf(type, s);
    }
    

    这里我们可以自定义类型转换, 我们可以通过给枚举类型定义一个私有的 int 类型的变量, 然后在保存时, 保存对应枚举类型的 int 变量, 在获取值时, 根据数据库查出来的 int 变量获取对应的枚举值.

    public class EnabledTypeHandler implements TypeHandler<Enabled> {
        private final Map<Integer, EnableEnum> enabledMap = new HashMap<>();
        
        public EnabledTypeHandler() {
            for (EnableEnum enabled : EnableEnum.values()) {
                enabledMap.put(enabled.getValue(), enabled);
            }
        }
    
        @Override
        public void setParameter(
                PreparedStatement preparedStatement, int i, EnableEnum enableEnum, JdbcType jdbcType) throws SQLException {
            // 保存时, 保存枚举对应的 int 值    
            preparedStatement.setInt(i, enableEnum.getValue());
        }
    
        @Override
        public EnableEnum getResult(ResultSet resultSet, String s) throws SQLException {
            Integer value = resultSet.getInt(s);
            // 查询时, 根据对应的枚举值
            return enabledMap.get(value);
        }
    
        @Override
        public EnableEnum getResult(ResultSet resultSet, int i) throws SQLException {
            Integer value = resultSet.getInt(i);
            // 查询时, 根据对应的枚举值
            return enabledMap.get(value);
        }
    
        @Override
        public EnableEnum getResult(CallableStatement callableStatement, int i) throws SQLException {
            Integer value = callableStatement.getInt(i);
            // 查询时, 根据对应的枚举值
            return enabledMap.get(value);
        }
    }
    
    <typeHanlders>
        <typeHandler
            javaType="study.EnabledEnum"
            handler="study.EnabledTypeHanlder"
        />
    </typeHandlers>
    
  3. Java 8 对日期(JSR-310)的支持: Mybatis 从 3.4.0 版本开始增加了对 Java 8 日期(JSR-310) 的支持. 如果是使用 3.4.0 及以上版本, 需要在 pom.xml 中引入依赖:

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-typehandlers-jsr310</artifactId>
        <version>1.0.2</version>
    </dependency>
    

    若是比 3.4.0 更早的版本, 还需要在 mybatis-config.xml 中添加如下配置:

    <typeHanlders>
        <typeHanlder handler="org.apache.ibatis.type.InstantTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.LocalDateTimeTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.LocalDateTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.LocalTimeTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.OffsetDateTimeTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.OffsetTimeTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.ZoneDateTimeTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.YearTypeHandler"/>
        <typeHanlder handler="org.apache.ibatis.type.MonthTypeHandler"/>
    </typeHandler>
    
  4. 参考:
    [1] : MyBatis从入门到精通