Mybatis 枚举值存取数据库处理

内置的枚举处理器

mybatis内置了两个枚举类型处理器,EnumTypeHandler和EnumOrdinalTypeHandler,这两个类型都不好用,一般也是我们自己实现枚举的类型处理器。

EnumTypeHandler存入数据库的是枚举的name,EnumOrdinalTypeHandler存入数据库的是枚举的位置。例如下方的枚举,当我们有一个枚举值是EStatus.init时,这时我们使用mybatis的EnumTypeHandler存入数据库的是”init”字符串;而EnumOrdinalTypeHandler存入的是3,因为init是第四个值,第一个值disable的index是0。

public enum EStatus {

    disable("0"), enable("1"), deleted("2"),
    init("10"), start("11"), wait("12"), end("13"); 
}

编写枚举接口约束

首先定义接口,提供获取数据库存取的值得方法,方便多个枚举,使用一个Handler处理

package com.join.payment.utils;

/**
 * 枚举约束
 */
public interface BaseCodeEnum {
    int getCode();//必须包含方法
}

编写 EnumTypeHandler

定义mybatis的typeHandler扩展类

package com.join.payment.utils;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

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

/**
 * 通用int 枚举转换器
 * @author 范文刚
 */
public class EnumTypeHandler extends BaseTypeHandler<BaseCodeEnum>{

    private Class<BaseCodeEnum> type;
    private final BaseCodeEnum[] enums;
    /**
     * 设置配置文件设置的转换类以及枚举类内容,供其余方法更便捷高效的实现
     * @param type 配置文件中设置的转换类
     */
    public EnumTypeHandler(Class<BaseCodeEnum> 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.");
        }
    }
    /**
     * 枚举类型转换,因为构造函数获取了枚举的子类enums,让遍历更加高效快捷
     * @param code 数据库中存储的自定义code属性
     * @return code对应的枚举类
     */
    private BaseCodeEnum locateEnumStatus(int code) {
        for(BaseCodeEnum status : enums) {
            if(status.getCode() ==code ) {
                return status;
            }
        }
        throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName());
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, BaseCodeEnum parameter, JdbcType jdbcType) throws SQLException {
        // baseTypeHandler已经作了parameter的null判断
        ps.setInt(i, parameter.getCode());
    }

    @Override
    public BaseCodeEnum 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 BaseCodeEnum 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 BaseCodeEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型
        int i = cs.getInt(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值,定位EnumStatus子类
            return locateEnumStatus(i);
        }
    }
}

举个OrderStateEnumde例子

package com.join.payment.domain;

import com.join.payment.utils.BaseCodeEnum;

/**
 * 订单状态
 * @author 范文刚
 */
public enum OrderStateEnum implements BaseCodeEnum {
    /**
     * 交易关闭
     */
    CLOSE(-1),
    /**
     * 默认
     */
    DEFAULT(0),
    /**
     * 交易中
     */
    APPLY(1),
    /**
     * 交易成功
     */
    SUCCESS(2);

    OrderStateEnum(int code)
    {
        this.code = code;
    }
    private final int code;

    @Override
    public int getCode(){ return code; }
}

Mapper 文件中修改处理器

<resultMap type="PayOrder" id="PayOrderResult">
    <result property="id"    column="id"    />
    <result property="state"    column="state" typeHandler="com.join.payment.utils.EnumTypeHandler"   />
</resultMap>
<insert id="insertPayOrder" parameterType="PayOrder">
        insert into pay_order
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="state != null">state,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id},</if>
            <if test="state != null">#{state,typeHandler=com.join.payment.utils.EnumTypeHandler},</if>
         </trim>
</insert>

 <update id="updatePayOrder" parameterType="PayOrder">
        update pay_order
        <trim prefix="SET" suffixOverrides=",">
            <if test="state != null">state = #{state,typeHandler=com.join.payment.utils.EnumTypeHandler},
        </trim>
        where id = #{id}
    </update>
上一篇
下一篇