Mybatis-自定义Enum映射

Posted zhang_xinxiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis-自定义Enum映射相关的知识,希望对你有一定的参考价值。

mybatis自定义Enum映射

前言

在使用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对象中,很方便。

以上是关于Mybatis-自定义Enum映射的主要内容,如果未能解决你的问题,请参考以下文章

mybatis类型转换器 - 自定义全局转换enum

springboot mybatis自定义枚举enum转换

mysql enum 对应mybatis啥类型

mybatis的enum重构

MyBatis映射文件 之 resultMap 自定义映射

自定义枚举 --- MyBatis字段映射