mybatis 中使用枚举

mybatis 中使用枚举


 

 

mybatis 中使用枚举

1. 内置枚举转换器

1.1 内置枚举转换器介绍

1.1.1 EnumTypeHandler

  • 默认的枚举转换器,该转换器将枚举实例转换为实例名称的字符串,即将 SexEnum.MAN 转换 MAN

1.1.2 EnumOrdinalTypeHandler

  • 将枚举实例的 ordinal 属性作为取值,即 SexEnum.MAN 转换为 0SexEnum.WOMAN转换为 1

MyBatis内置枚举转换器

  • org.apache.ibatis.type.EnumTypeHandler
  • org.apache.ibatis.type.EnumOrdinalTypeHandler

 

1.2 内置枚举转换器使用

mybatis-config.xml

<typeHandlers>
	<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.answer.aal.entity.StatusEnum" />
	<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
</typeHandlers>
  • 1
  • 2
  • 3
  • 4

 


2. 自定义类型转换器

2.1 BaseTypeHandler 抽象类

public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {

// ...

  /**
     * 用于定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型
     * */
  public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) 
						throws SQLException;

  /**
     * 用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型
     * */
  public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;

  /**
     * 用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型
     * */
  public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;

  /**
     * 用定义调用存储过程后,如何把数据库类型转换为对应的Java类型
     * */
  public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;

}

 

 

 

2.2 自定义枚举转换器实现

2.2.1 枚举接口

枚举通用行为接口: IEnum

public interface IEnum<E extends Enum<?>, T> {

    T getValue();

}

 

 
性别枚举: SexEnum

public enum SexEnum implements IEnum<EducationEnum, Integer> {

    /** 男 */
    MAN(0),

    /** 女 */
    WOMAN(1);

    private int value;

    SexEnum(int value) {
        this.value = value;
    }

    @Override
    public Integer getValue() {
        return value;
    }
}

 

 
学历枚举: EducationEnum

public enum EducationEnum implements IEnum<EducationEnum, String> {

    /** 小学 */
    PRIMARY_SCHOOL("PRIMARY"),

    /**
     * 初中
     * */
    JUNIOR_SCHOOL("JUNIOR"),

    /**
     * 高中
     * */
    HIGH_SCHOOL("HIGH"),

    /**
     * 大学
     * */
    UNIVERSITY_SCHOOL("UNIVERSITY")
    ;

    private String value;

    EducationEnum(String value) {
        this.value = value;
    }

    @Override
    public String getValue() {
        return value;
    }
}

 

 

2.2.2 自定义类型转换器

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

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

@MappedTypes(value = {SexEnum.class, EducationEnum.class})
public class BaseEnumTypeHandler<E extends Enum<E> & IEnum> extends BaseTypeHandler<E> {

    /**
     * 枚举的class
     */
    private Class<E> type;
    /**
     * 枚举的每个子类枚
     */
    private E[] enums;

    /**
     * 一定要有默认的构造函数, 不然抛出 not found method 异常
     */
    public BaseEnumTypeHandler() {
    }

    /**
     * 设置配置文件设置的转换类以及枚举类内容, 供其他方法更便捷高效的实现
     *
     * @param type 配置文件中设置的转换类
     */
    public BaseEnumTypeHandler(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.");
        }
    }

    /**
     * 用于定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型
     * */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
                                    JdbcType jdbcType) throws SQLException {
        /*
         * BaseTypeHandler已经帮我们做了parameter的null判断
         * 数据库存储的是枚举的值, 所以我们这里使用 value ,  如果需要存储 name, 可以自定义修改
         */
        if (jdbcType == null) {
            ps.setString(i, Objects.toString(parameter.getValue()));
        } else {
            ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
        }
    }

    /**
     * 用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型
     * */
    @Override
    public E getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        String i = rs.getString(columnName);
        if (rs.wasNull()) {
            return null;
        } else {
            return locateEnumStatus(i);
        }
    }

    /**
     * 用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型
     * */
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        String i = rs.getString(columnIndex);
        if (rs.wasNull()) {
            return null;
        } else {
            return locateEnumStatus(i);
        }
    }

    /**
     * 用定义调用存储过程后,如何把数据库类型转换为对应的Java类型
     * */
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        String i = cs.getString(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            return locateEnumStatus(i);
        }
    }

    /**
     * 枚举类型转换
     * 
     * @param value 数据库中存储的自定义value属性
     * @return value 对应的枚举类
     */
    private E locateEnumStatus(String value) {
        for (E e : enums) {
            if (Objects.toString(e.getValue()).equals(value)) {
                return e;
            }
        }
        throw new IllegalArgumentException("未知的枚举类型:" + value + ",请核对"
                + type.getSimpleName());
    }

}

注意: 如果使用了 @MappedTypes 注解, 需要在 application.properties 中添加如下配置

# 类型处理器类所在的包路径. eg: BaseEnumTypeHandler
mybatis.type-handlers-package=com.answer.aal.entity
  •  

否则, 直接在 mybatis 配置文件 mybatis-config.xml 添加如下配置

<typeHandlers>
	<typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.EducationEnum" />
	<typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
</typeHandlers>
  •  

2.3 自定义枚举转换器测试

2.3.1 用户实体对象

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
/**
 * MyBatis 映射的实体对象必须提供一个无参构造方法
 * */
@NoArgsConstructor
public class User {

    /**
     * 主键ID
     * */
    private Long id;

    private String userName;

    private SexEnum sex;

    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birthDay;

    private EducationEnum education;

    @JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
    private Date createTime;

    @JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
    private Date updateTime;

    public User(String userName, SexEnum sex, Date birthDay, EducationEnum education, Date createTime, Date updateTime) {
        this.userName = userName;
        this.sex = sex;
        this.birthDay = birthDay;
        this.education = education;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }
}
  •  

2.3.2 控制层

import com.answer.aal.entity.SexEnum;
import com.answer.aal.entity.EducationEnum;
import com.answer.aal.entity.User;
import com.answer.aal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private IUserService userService;

    @RequestMapping("findUsers")
    public List<User> findUsers() {
        return userService.findUsers();
    }


    @RequestMapping("finUserById/{id}")
    public User finUserById(@PathVariable("id") Long id) {
        return userService.findUserById(id);
    }

    @RequestMapping("insert")
    public Long insert(){
        User user = new User("AnsweAIL", SexEnum.MAN, new Date(), EducationEnum.HIGH_SCHOOL, new Date(), new Date());

        return userService.insertUer(user);
    }

}

 

2.3.3 接口层

import com.answer.aal.entity.User;
import java.util.List;

public interface IUserService {

    List<User> findUsers();

    User findUserById(Long id);

    Long insertUer(User user);

} 

 

2.3.4 接口实现层

import com.answer.aal.dao.UserDao;
import com.answer.aal.entity.User;
import com.answer.aal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserDao userDao;

    @Override
    public List<User> findUsers() {
        return userDao.findUsers();
    }

    @Override
    public User findUserById(Long id) {
        return userDao.findUserById(id);
    }

    @Override
    public Long insertUer(User user) {
        return userDao.insertUer(user);
    }
}
  •  

 

2.3.5 持久层

import com.answer.aal.entity.User;

import java.util.List;

public interface UserDao {

    List<User> findUsers();

    User findUserById(Long id);

    Long insertUer(User user);

}
  •  

 

2.3.6 mybatis 配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <typeAlias alias="User" type="com.answer.aal.entity.User"/>
    </typeAliases>

    <typeHandlers>
    	<!-- 如果此处配置了映射, 则 BaseEnumTypeHandler 中就不需要 @MappedTypes 注解和 application.xml 中不需要设置属性 mybatis.type-handlers-package 值 -->
        <typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.xsf.entity.EducationEnum" />
        <typeHandler handler="com.answer.xsf.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
    </typeHandlers>

</configuration>

 

注意: 如果 BaseEnumTypeHandler 中设置了 @MappedTypes 注解, 此步骤 mybatis 配置文件 可省去
 

2.3.7 mybatis 映射文件

<?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.answer.aal.dao.UserDao" >

    <resultMap id="user_mapper" type="User">
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="user_name" property="userName" jdbcType="VARCHAR" />
        <result column="sex" property="sex" />
        <result column="birth_day" property="birthDay" jdbcType="DATE" />
        <result column="education" property="education" />
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
    </resultMap>
    
    <sql id="user_columns">
        id, user_name, sex, birth_day, education, create_time, update_time
    </sql>

    <select id="findUsers" resultMap="user_mapper">
        select <include refid="user_columns" />
        from sf_user
    </select>

    <select id="findUserById" resultMap="user_mapper">
        select <include refid="user_columns" />
        from sf_user
        where id = #{id}
    </select>

    <insert id="insertUer" useGeneratedKeys="true" keyProperty="id">
        insert into sf_user
        <trim prefix="(" suffix=")" suffixOverrides="," >
            <if test="userName != null" >user_name,</if>
            <if test="sex != null" >sex,</if>
            <if test="birthDay != null" >birth_day,</if>
            <if test="education != null" >education,</if>
            <if test="createTime != null" >create_time,</if>
            <if test="updateTime != null" >update_time,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
            <if test="userName != null" >#{userName},</if>
            <if test="sex != null" >#{sex},</if>
            <if test="birthDay != null" >#{birthDay},</if>
            <if test="education != null" >#{education},</if>
            <if test="createTime != null" >#{createTime},</if>
            <if test="updateTime != null" >#{updateTime},</if>
        </trim>
    </insert>
    
</mapper>

 

2.4 数据库脚本

CREATE TABLE `sf_user` (
  `id` bigint(18) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(20) DEFAULT NULL,
  `sex` enum('1','0') DEFAULT '0',
  `birth_day` date DEFAULT NULL,
  `education` enum('UNIVERSITY','HIGH','JUNIOR','PRIMARY') DEFAULT 'PRIMARY',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

 

 

2.5 接口测试

在这里插入图片描述
 

2.6 Reference

posted @ 2020-11-14 01:40  kelelipeng  阅读(1184)  评论(0编辑  收藏  举报