zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    SQL函数说明大全
    (火炬)MS SQL Server数据库案例教程
    SQL 数据库基础语句
    java 中length,length(),size()的区别
    关于webLogic启动问题
    dreamweaver读jsp时遇到的问题
    Microsoft 注册表编辑器 (regedit.exe)
    由正则表达式REGEXP_REPLACE开始
    Hello World
    Python基础目录
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/13972120.html
Copyright © 2011-2022 走看看