设为首页 收藏本站
查看: 2289|回复: 0

[经验分享] 在mybatis中使用枚举和boolean,提供代码可读性

[复制链接]

尚未签到

发表于 2016-11-28 10:12:23 | 显示全部楼层 |阅读模式
问题描述
  实体中的属性使用枚举和boolean会增加代码的可读性,但是实体和数据库的映射上不能很自然地支持,这样导致由于数据库的原因使得实体中属性使用基本类型来代替枚举和boolean。
  实体中属性实例如下
  private Integer status;// 0:草稿,1:合格 2:优秀 3:退回
  private Byte open;//0;关闭 1:打开
  在页面,java代码,和sql到处使用数字,使得代码可读性极差,代码越多,时间越长越没法维护。
  <#if trainGroup.type==1>
<a href="javascript:" class="zi-lv"  >教研组</a>
<#else>
<a href="javascript:" class="zi-lv"  >协作组</a>
</#if>
  param.setStatus(2); //优秀
  或者使用常量(不能保证大家都使用常量,直接使用数字也没有错)param.setStatus(CONST.GOOD); //优秀
  select ....
      from T_DT_TRAIN_GROUP t .....m.STATUS = 2
使用枚举后的代码如下
  <#if trainGroup.type=='JIAOYAN'>
<a href="javascript:" class="zi-lv"  >教研组</a>
<#else>
<a href="javascript:" class="zi-lv"  >协作组</a>
</#if>
  param.setStatus(Status.GOOD);//只能使用枚举,否则编译通不过
select ....
      from T_DT_TRAIN_GROUP t .....m.STATUS =${@cn.com.Status@GOOD.getValue()}

解决办法
  在mybatis中实体属性与表字段之间的映射使用TypeHandler机制,mybatis本身提供了两种枚举类型的转换 EnumTypeHandler和EnumOrdinalTypeHandler。
  EnumTypeHandler:将枚举值转化成字符串,字符串取枚举值的名称,使用枚举的.name()方法。EnumTypeHandler已经被内置了,只需要将实体属性改成枚举即可,不需要做任何TypeHandler配置,下面是mybatis获得TypeHandler的源码,如果没有匹配上任何TypeHandler,并且属性是枚举类型就使用EnumTypeHandler。
    private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
    TypeHandler<?> handler = null;
    if (jdbcHandlerMap != null) {
      handler = jdbcHandlerMap.get(jdbcType);
      if (handler == null) {
        handler = jdbcHandlerMap.get(null);
      }
    }
    if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) {
      handler = new EnumTypeHandler((Class<?>) type);
    }
    @SuppressWarnings("unchecked")
    // type drives generics here
    TypeHandler<T> returned = (TypeHandler<T>) handler;
    return returned;
  }

  这种方式最简洁,不需要做任何配置,但是要求表字段中存储的是枚举的名称。
  EnumOrdinalTypeHandler:将枚举值转换数字,使用的是枚举的.ordinal()方法。如果要使用这种方式必须给每一个枚举类配置一次EnumOrdinalTypeHandler,如下给两个枚举配置同一个
   EnumOrdinalTypeHandler,没有配置的枚举会走默认的EnumTypeHandler。
     <typeHandlers>
        <!-- <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
            javaType="cn.com.teacher.cistus.dt.entity.TestMenu" /> -->
        <typeHandler
            handler="
org.apache.ibatis.type.EnumOrdinalTypeHandler"
            javaType="cn.com.teacher.cistus.dt.enums.EnumTrainGroupType" />
        <typeHandler
            handler="
org.apache.ibatis.type.EnumOrdinalTypeHandler"
            javaType="cn.com.teacher.cistus.dt.enums.EnumPortalConfigType" />
    </typeHandlers>

 sql mapper中如何使用枚举
  public class TrainGroup extends AbstractEntity
  private EnumTrainGroupType type;//0教研组 1协作组
  映射和查询条件中不用任何特殊处理即可使用枚举。
  <resultMap id="BaseResultMap" type="cn.com.teacher.cistus.dt.entity.TrainGroup" >
  <result column="TYPE" property="type" jdbcType="INTEGER" />
  。。。
  <if test="type != null" >
        TYPE = #{type,jdbcType=INTEGER},
      </if>
sql中使用枚举常量
  如下示例直接在sql中使用枚举,这样提高了代码的可读性,并且枚举值写错了会报错提示的。type=${@cn.com.teacher.cistus.
dt.enums.EnumTrainGroupType@JIAOYAN.ordinal()}

枚举常量的获取使用了ongl表达式的功能,${@cn.co。。GroupType@JIAOYAN.ordinal()}是原生的ongl执行静态代码的写法。

枚举值按指定值映射
  mybatis本身只提供了上面两种枚举映射方式,如果想映射自定义的值,比如
  JIAOYAN(10,"教研组"),XIEZUO(20,"协作组");映射成 10 ,20.
  public class EnumValueTypeHandler <E extends Enum & IDBEnum> extends BaseTypeHandler<E>{
    private Class<E> type;
     // private final E[] enums;

      public EnumValueTypeHandler(Class<E> type) {
        this.type = type;
        E[] enums = type.getEnumConstants();
        if (enums == null) {
          throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
        }
      }

      @Override
      public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getValue());
      }

      @Override
      public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int i = rs.getInt(columnName);
        if (rs.wasNull()) {
          return null;
        } else {
          try {
            return DBEnumUtils.getEnumInstance(type,i);
          } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
          }
        }
      }

      @Override
      public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int i = rs.getInt(columnIndex);
        if (rs.wasNull()) {
          return null;
        } else {
          try {
              return DBEnumUtils.getEnumInstance(type,i);
          } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
          }
        }
      }

      @Override
      public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int i = cs.getInt(columnIndex);
        if (cs.wasNull()) {
          return null;
        } else {
          try {
              return DBEnumUtils.getEnumInstance(type,i);
          } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
          }
        }
      }
}

  public enum EnumTrainGroupType implements IDBEnum{
    JIAOYAN(10,"教研组"),XIEZUO(20,"协作组");

    private int value;
    private String name;
    EnumTrainGroupType(int value,String name){
        this.value=value;
        this.name=name;
    }
    @Override
    public int getValue() {
        return value;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setValue(int value) {
        this.value = value;
    }

}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-306526-1-1.html 上篇帖子: MyBatis的Map中放集合对象(为了in操作等)的小提示 下篇帖子: mybatis配置,关于mapper.java与mapper.xml是否在一个文件夹中
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表