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

平时咱们写程序实体类内或多或少都会有枚举类型属性,方便嘛。但是mybatis里怎么处理他们的增删改查呢?

要求:

插入的时候,会用枚举的定义插入数据库,我们希望在数据库中看到的是数字或者其他东西;

查询的时候,数据库的值可以自动转换为我们对应的枚举值。

举例,我有一个这样的枚举类型:

public enum UserStatus {  
  
    /** 无效*/  
    DISABLED(0),  
    /** 有效 */  
    AVAILABLE(1);  
      
    private int status;  
      
    UserStatus(int status){  
        this.status = status;  
    }  
  
    public int getStatus() {  
        return status;  
    }  
      
}  

我们插入数据库中,数据库应该为我们保存0或者1

我们可以使用mybatis自带的枚举类型EnumOrdinalTypeHandler

举例如下:

<insert id="addUser" parameterType="User">  
    INSERT INTO t_user(USER_ID,USER_NAME,LOGIN_NAME,  
    LOGIN_PASSWORD,USER_STATUS,CREATE_TIME,UPDATE_TIME)  
    VALUES(  
        #{user_id},  
        #{user_name},  
        #{login_name},  
        #{login_password},  
        #{user_status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},  
        #{create_time},  
        #{update_time}  
    )  
</insert>  

我们的UserStatus插入的时候是UserStatus.AVAILABLE

执行完毕后,看结果:

我们查询的时候报错了:Error querying database.  Cause: java.lang.IllegalArgumentException: No enum constant cn.com.shuyangyang.mybatis.UserStatus.1

 

我们可以自定义这样的一个EnumStatusHandler:

import java.sql.CallableStatement;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
import org.apache.ibatis.type.BaseTypeHandler;  
import org.apache.ibatis.type.JdbcType;  
  
/** 
 * Mybatis自定义转换类型 
 * @author ShuYangYang 
 * E-Mail:shuyangyang@aliyun.com 
 * http://www.shuyangyang.com.cn 
 * Date:2015年1月26日下午10:12:54 
 * 
 */  
public class EnumStatusHandler extends BaseTypeHandler<UserStatus> {  
      
    private Class<UserStatus> type;  
       
    private final UserStatus[] enums;  
   
    /** 
     * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 
     * @param type 配置文件中设置的转换类 
     */  
    public EnumStatusHandler(Class<UserStatus> 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,  
            UserStatus parameter, JdbcType jdbcType) throws SQLException {  
        // baseTypeHandler已经帮我们做了parameter的null判断  
        ps.setInt(i, parameter.getStatus());  
          
    }  
  
    @Override  
    public UserStatus getNullableResult(ResultSet rs, String columnName)  
            throws SQLException {  
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
        int i = rs.getInt(columnName);  
           
        if (rs.wasNull()) {  
            return null;  
        } else {  
            // 根据数据库中的code值,定位EnumStatus子类  
            return locateEnumStatus(i);  
        }  
    }  
  
    @Override  
    public UserStatus getNullableResult(ResultSet rs, int columnIndex)  
            throws SQLException {  
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
        int i = rs.getInt(columnIndex);  
        if (rs.wasNull()) {  
            return null;  
        } else {  
            // 根据数据库中的code值,定位EnumStatus子类  
            return locateEnumStatus(i);  
        }  
    }  
  
    @Override  
    public UserStatus getNullableResult(CallableStatement cs, int columnIndex)  
            throws SQLException {  
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
        int i = cs.getInt(columnIndex);  
        if (cs.wasNull()) {  
            return null;  
        } else {  
            // 根据数据库中的code值,定位EnumStatus子类  
            return locateEnumStatus(i);  
        }  
    }  
      
    /** 
     * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷 
     * @param code 数据库中存储的自定义code属性 
     * @return code对应的枚举类 
     */  
    private UserStatus locateEnumStatus(int code) {  
        for(UserStatus status : enums) {  
            if(status.getStatus()==(Integer.valueOf(code))) {  
                return status;  
            }  
        }  
        throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName());  
    }  
  
}  

mapper.xml里这样配置:

<resultMap type="User" id="userResult">  
……省略其他属性配置  
        <result column="USER_STATUS" property="user_status" typeHandler="cn.com.hekliu.mybatis.EnumStatusHandler"/>  
……省略其他属性配置  
    </resultMap>  

现在来看看结果:

 [User [user_id=782cba19-559f-41c3-a1b0-25fcac4cf118, user_name=系统管理员, login_name=admin, login_password=admin,user_status=AVAILABLE, create_time=Mon Jan 26 21:17:09 CST 2018, update_time=Mon Jan 26 21:17:09 CST 2018]]

 

完美结果。

MyBatis中,我们可以使用TypeHandler来处理Java中的枚举类型与SQL中的映射关系。具体操作如下: 1. 创建一个实现了TypeHandler接口的枚举类型转换器类。 ``` public class MyEnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> { private Class<E> type; public MyEnumTypeHandler(Class<E> type) { if (type == null) throw new IllegalArgumentException("Type argument cannot be null"); this.type = type; } @Override public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException { if (parameter == null) { ps.setNull(i, jdbcType.TYPE_CODE); } else { ps.setInt(i, parameter.ordinal()); } } @Override public E getResult(ResultSet rs, String columnName) throws SQLException { int ordinal = rs.getInt(columnName); if (rs.wasNull()) { return null; } else { try { Method method = type.getMethod("values"); Object[] objects = (Object[]) method.invoke(type); return (E) objects[ordinal]; } catch (Exception e) { throw new IllegalArgumentException("Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", e); } } } @Override public E getResult(ResultSet rs, int columnIndex) throws SQLException { int ordinal = rs.getInt(columnIndex); if (rs.wasNull()) { return null; } else { try { Method method = type.getMethod("values"); Object[] objects = (Object[]) method.invoke(type); return (E) objects[ordinal]; } catch (Exception e) { throw new IllegalArgumentException("Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", e); } } } @Override public E getResult(CallableStatement cs, int columnIndex) throws SQLException { int ordinal = cs.getInt(columnIndex); if (cs.wasNull()) { return null; } else { try { Method method = type.getMethod("values"); Object[] objects = (Object[]) method.invoke(type); return (E) objects[ordinal]; } catch (Exception e) { throw new IllegalArgumentException("Cannot convert " + ordinal + " to " + type.getSimpleName() + " by ordinal value.", e); } } } } ``` 2. 在MyBatis的配置文件中注册这个TypeHandler。 ``` <typeHandlers> <typeHandler handler="com.example.MyEnumTypeHandler" javaType="com.example.MyEnum"/> </typeHandlers> ``` 3. 在Java对象中使用枚举类型。 ``` public class User { private Long id; private String name; private Gender gender; // getter and setter } ``` 4. 在SQL语句中使用枚举类型。 ``` <select id="getUser" parameterType="long" resultType="com.example.User"> select * from user where id = #{id} </select> ``` 这样,MyBatis就会自动将数据库中的值转换为Java对象中的枚举类型,或者将Java对象中的枚举类型转换为数据库中的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hekliu

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值