【Mybatis】-自定义Enum映射

本文详细介绍了在Mybatis中如何处理自定义枚举的映射问题。当数据库中的枚举值与Java实体类中的枚举不匹配时,不能直接使用EnumTypeHandler或EnumOrdinalTypeHandler。文章讲解了如何创建自定义枚举类型控制器,通过在mybatis配置文件中注册该控制器,实现在映射过程中将数据库中的枚举值正确地映射到Java对象上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在使用mybatis作为orm映射时往往会涉及到枚举值的映射,如果mysql数据库中的数据使用的是enum类型,那么映射到系统中对应的值也应该是一个枚举字段,mybatis提供了枚举值的自动映射,分别是EnumTypeHandler和EnumOrdinalTypeHandler两个控制类来实现的,是针对的普通枚举来映射的,但是对于自定义的复杂枚举这两种根本就无法处理,需要自定义一个枚举类型控制器,如下将会详细介绍自定义枚举控制器的方法。

映射具体实现

程序准备

数据结构

 CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT '',
  `store` int(11) DEFAULT '0',
  `sex` enum('M','F','N') DEFAULT NULL,
  `is_enable` smallint(6) DEFAULT '0',
  `utime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `ctime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

需要映射的实体类

package com.jesse.modules.test;

import com.jesse.modules.test.enums.EnableEnum;
import com.jesse.modules.test.enums.SexEnum;

import java.util.Date;

public class TestModel {

    private int id;
    private String name;
    private Integer store;
    private Date utime;
    private Date ctime;
    private SexEnum sex;
    private EnableEnum isEnable;

    public Integer getStore() {
        return store;
    }

    public void setStore(Integer store) {
        this.store = store;
    }

    public Date getUtime() {
        return utime;
    }

    public void setUtime(Date utime) {
        this.utime = utime;
    }

    public Date getCtime() {
        return ctime;
    }

    public void setCtime(Date ctime) {
        this.ctime = ctime;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public SexEnum getSex() {
        return sex;
    }

    public void setSex(SexEnum sex) {
        this.sex = sex;
    }

    public EnableEnum getIsEnable() {
        return isEnable;
    }

    public void setIsEnable(EnableEnum enable) {
        isEnable = enable;
    }
}

程序的枚举类

package com.jesse.modules.test.enums;

public enum SexEnum {
    M("Male","男"),
    F("Female","女"),
    N("None","未知");

    private String sex;
    private String type;
    SexEnum(String sex,String type){
        this.sex=sex;
        this.type=type;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
public enum  EnableEnum {
    T(1,true),
    F(2,false);
    private int index;
    private boolean type;

    EnableEnum(int index,boolean type){
        this.index=index;
        this.type=type;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public boolean isType() {
        return type;
    }

    public void setType(boolean type) {
        this.type = type;
    }

}

简单枚举映射

上面需要映射的有两中分别是SexEnum和EnableEnum,在处理时由于SexEnum是简单枚举,数据库值对应的就是java实体类的枚举名称,这种不需要自定义枚举,只需在mapper文件中指定typeHandler即可,如下的映射方法:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jesse.modules.test.dao.IDaoReader.ITestReader">

    <resultMap id="BaseResultMap" type="com.jesse.modules.test.TestModel">
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="store" property="store" jdbcType="INTEGER" />
        <result column="utime" property="utime" jdbcType="TIMESTAMP"/>
        <result column="ctime" property="ctime" jdbcType="TIMESTAMP" />
        <result column="sex" property="sex" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
        <result column="is_enable" property="isEnable" javaType="com.jesse.modules.test.enums.EnableEnum"/>
    </resultMap>

    <sql id="Base_Column_List" >
        id, name,store,utime,ctime,sex,is_enable
    </sql>

    <sql id="tableName">product</sql>
    <sql id="where">
        <where>
            <if test="id!=null and id!=0">
                id=#{id}
            </if>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="store!=null and store!=0">
                and store=#{store}
            </if>
            <if test="utime !=null">
                and ctime=#{ctime}
            </if>
        </where>
    </sql>
    <select id="getById" parameterType="com.jesse.modules.test.TestModel" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_List"/>
        FROM
        <include refid="tableName"/>
        <include refid="where"/>
    </select>
</mapper>

使用EnumTypeHandler来自动将数据库的值映射到对应的java实体对象中,不需要自定义复杂实体映射。

复杂枚举映射

对于EnableEnum映射来说,程序就变得很复杂,首先数据库中存的枚举值既不是java枚举类中的索引,又不是java枚举类中的名称,这种EnumTypeHandler和EnumOrdinalTypeHandler都是无法处理的,这时候必须自定义一个复杂的枚举映射控制实现,并且要在mybatis中注册。具体实现方法如下。

添加自定义映射控制类

如下代码是自己添加的自定义的枚举映射控制类,主要实现思路是mybatis在加载时将数据库中的值作为枚举的索引,对应的枚举作为value,缓存到enums属性中,然后通过get获取到指定的枚举。

package com.jesse.modules.typeHandler;

import com.jesse.modules.test.enums.EnableEnum;
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;
import java.util.Hashtable;

public class EnumHandler<E extends EnableEnum> extends BaseTypeHandler<E> {
    private Class<E> type;
    private final Hashtable<Integer,E> enums;

    public EnumHandler(Class<E> type) {
        this.type=type;
        E[] enums1=type.getEnumConstants();

        enums=new Hashtable<Integer,E>();
        for (E e : enums1) {
            enums.put(e.getIndex(),e);
        }

    }
    @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);
        return enums.get(i);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int i=rs.getInt(columnIndex);
        return enums.get(i);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int i=cs.getInt(columnIndex);
        return enums.get(i);
    }
}

mybatis配置

把下面的mybatis配置放到程序的resources下面的core文件夹中,命名为mybatis-config.xml。

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeHandlers>
        <typeHandler handler="com.jesse.modules.typeHandler.EnumHandler" javaType="com.jesse.modules.test.enums.EnableEnum"/>
    </typeHandlers>
</configuration>

对应的spring中的注解

<bean id="readerSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="readerDataSource"/>
        <property name="mapperLocations" value="classpath*:mybatis/modules/**/reader/*Mapper.xml"/>
        <property name="configLocation" value="classpath:core/mybatis-config.xml"/>
</bean>

结语

至此自定义映射部分,已经配置完成,完整的自定义映射需要将配置的控制器注册到对应的处理枚举类中,这就是mybatis-config.xml要做的,接下来运行程序,会自动将枚举值映射到java对象中,很方便。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值