mybatis 处理枚举类型

Posted Magic_Li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis 处理枚举类型相关的知识,希望对你有一定的参考价值。

MyBatis支持持久化enum类型属性。假设t_user表中有一列gender(性别)类型为 varchar2(10),存储 MALE 或者 FEMALE 两种值。并且,User对象有一个enum类型的gender 属性,如下所示:

public enum Gender { 
MALE,FEMALE; 
}

 

默认情况下MyBatis使用EnumTypeHandler来处理enum类型的Java属性,并且将其存储为enum值的名称。我们不需要为此做任何额外的配置。可以像使用基本数据类型属性一样使用enum类型属性,如下:

create table t_user(
          id number primary key,
          name varchar2(50),
          gender varchar2(10)
);

 

public class User{ 
            private Integer id; 
            private String name; 
            private Gender gender; 

            //setters and getters 
} 

 映射文件:

<insert id="insertUser" parameterType="User"> 
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        select my_seq.nextval from dual
    </selectKey>
    insert into t_user(id,name,gender) 
    values(#{id},#{name},#{gender}) 
</insert>

映射接口:

public interface XxxxMapper{
    int insertUser(User user);    
}

测试方法:

@Test
public void test_insertUser(){

SqlSession sqlSession = null;
try {
sqlSession = MyBatisSqlSessionFactory.openSession();

SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);
User user = new User("tom",Gender.MALE);

mapper.insertUser(user);

sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
}
}

 

当执行insertStudent语句的时候MyBatis会取Gender枚举(FEMALE/MALE)的名称,存储到GENDER列中。

如果你想存储FEMALE为0,MALE为1到gender列中,需要在mybatis-config.xml文件中配置专门的类型处理器,并指定它处理的枚举类型是哪个。
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.briup.special.Gender"/>

EnumOrdinalTypeHandler这是个类型处理器,源码中有个set方法就是在帮助我们存值,源码如下

/**
 *    Copyright 2009-2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Clinton Begin
 */
public class EnumOrdinalTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {

  private final Class<E> type;
  private final E[] enums;

  public EnumOrdinalTypeHandler(Class<E> type) {
    if (type == null) {
      throw new IllegalArgumentException("Type argument cannot be null");
    }
    this.type = type;
    this.enums = type.getEnumConstants();
    if (this.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.ordinal());
  }

  @Override
  public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
    int i = rs.getInt(columnName);
    if (rs.wasNull()) {
      return null;
    } else {
      try {
        return enums[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 enums[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 enums[i];
      } catch (Exception ex) {
        throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);
      }
    }
  }
  
}

枚举类型的【顺序值】是根据enum中的声明顺序赋值的。如果改变了Gender里面对象的声明顺序,则数据库存储的数据和此顺序值就不匹配了。

以上是关于mybatis 处理枚举类型的主要内容,如果未能解决你的问题,请参考以下文章

mybatis扩展之自定义类型处理器处理枚举类型

mybatis中对枚举类型的处理

MyBatis配置项--处理枚举类型

MyBatis对于Java对象里的枚举类型处理

关于Mybatis中使用自定义类型通过 自定义TypeHandler类型处理器进行类型转换的两种配置方案-枚举类型示例

#yyds干货盘点# mybatis源码解读:executor包(语句处理功能)