关于Mybatis中使用自定义类型通过 自定义TypeHandler类型处理器进行类型转换的两种配置方案-枚举类型示例

关于Mybatis中使用自定义类型通过 自定义TypeHandler类型处理器进行类型转换的两种配置方案-枚举类型示例

参考书籍:Java EE互联网轻量级框架整合开发 杨开振 周吉文等著 (书中描述相对混杂)

环境介绍

IDEA-2018 Maven项目
数据库: Mysql

情景与实现目标

针对向Java程序向Mysql数据库中
插入 自定义Enum枚举类型
采用 自定义的类型转换器 进行处理。(示例为SexEnum类型转为Integer类型)
从而使自定义类型(枚举类型示例)能使用自定义的转换器安全的向数据库中
实现数据记录的传递

配置前的准备工作

整体项目组织结构(较乱勿喷,有些额外文件)

在这里插入图片描述

1. Java程序的目标POJO类-User (User.java)
public class User {
    private Long id;
    private String userName;
    private SexEnum sex;
    private String mess;

    public Long getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public SexEnum getSex() {
        return sex;
    }

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

    public String getMess() {
        return mess;
    }

    public void setMess(String mess) {
        this.mess = mess;
    }

    public String toString(){
        return userName +"[" + sex +"]: " + mess;
    }
}
2 POJO类User中使用的枚举类型SexEnum (SexEnum.java)
public enum SexEnum {
    MALE(0, "男"),
    FEMALE(1, "女");

    private int id;
    private String name;

    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;
    }

    SexEnum(int id, String name){
        this.id = id;
        this.name = name;
    }

    /**
     * 为方便自定义类型处理器转换所使用的辅助静态方法
     * @param id
     * @return
     */
    public static SexEnum getSexByID(int id){
        for(SexEnum sex: SexEnum.values()){
            if(sex.getId() == id){
                return sex;
            }
        }
        return null;
    }
}
3 User类对应的数据库中的表(user)

在这里插入图片描述

4.1 针对POJO类User的映射接口 (UserMapper.java)
public interface UserMapper {
    User getUser(Long id);
    int insertUser(User user);
    int deleteUser(Long id);
}
4.2 针对POJO类User的映射配置文件 (初始未配置版本,必然转换自定义类型失败) (UserMapper.xml)
<?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.castle.mapper.UserMapper">
    <!--在编写SQL语句时,数据库字段必须对应好POJO类的相应属性,若不一致使用AS指定-->
    <select id="getUser" parameterType="long" resultType="com.castle.POJO.User" >
        SELECT id, user_name AS userName, sex, mess FROM `user` WHERE id = #{id}
    </select>
    <insert id="insertUser" parameterType="com.castle.POJO.User">
        INSERT `user`(id, user_name, sex, mess) VALUES (#{id}, #{userName}, #{sex}, #{mess})
    </insert>

</mapper>
5 整个Maven项目的Mybatis配置文件(mybatis-config.xml,初始未配置版本,必然转换自定义类型失败)
<?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>

    <!--引入外部properties文件以获取外部属性引用-->
    <properties resource="jdbc.properties"/>

    <!--数据库环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${database.driver}"/>
                <property name="url" value="${database.url}"/>
                <property name="username" value="${database.username}"/>
                <property name="password" value="${database.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!--映射文件-->
    <mappers>
    	<!--注册先前编写的UserMapper.xml文件-->
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
5.1 关于Maven项目如何查找静态资源 xml文件 的注意事项

由于IDEA默认忽略自定义xml配置文件(如UserMapper.xml),会导致即使路径正确也无法找到相应的xml文件。
解决办法:在整个Maven项目的pom.xml配置文件中进行注册。需要使用指定配置文件时(如UserMapper.xml),可以直接使用文件名,不必在乎路径。
具体修改pom.xml文件(在< build >标签下 将指定目录的任意.xml文件添加为项目资源):

参见文章
mybatis配置文件和mapper类配置文件查找路径及具体引用方法

6 自定义类型转换器(SexHandler.java)
public class SexHandler implements TypeHandler<SexEnum> {

    Logger logger = Logger.getLogger(SexHandler.class);

    /**
     * 将SexEnum的id写入数据库做数据库数据
     * @param preparedStatement
     * @param i
     * @param sexEnum
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, SexEnum sexEnum, JdbcType jdbcType) throws SQLException {
        preparedStatement.setInt(i, sexEnum.getId());
        logger.info("输入完数据库sex参数:" + sexEnum);
    }

    /**
     * 根据数据库的整形数据,再借助SexEnum的类方法,返回相应的SexEnum类型
     * @param resultSet
     * @param s
     * @return
     * @throws SQLException
     */
    @Override
    public SexEnum getResult(ResultSet resultSet, String s) throws SQLException {
        int id = resultSet.getInt(s);
        SexEnum result = SexEnum.getSexByID(id);
        logger.info("输出数据库sex参数:" + result);
        return result;
    }

    @Override
    public SexEnum getResult(ResultSet resultSet, int i) throws SQLException {
        int id = resultSet.getInt(i);
        SexEnum result = SexEnum.getSexByID(id);
        logger.info("输出数据库sex参数:" + result);
        return result;
    }

    @Override
    public SexEnum getResult(CallableStatement callableStatement, int i) throws SQLException {
        int id = callableStatement.getInt(i);
        SexEnum result = SexEnum.getSexByID(id);
        logger.info("输出数据库sex参数:" + result);
        return result;
    }
}

解决方案1: 通过整个Mybatis项目配置声明处理自定义类型时使用自定义Handler转换器

具体做法:修改mybatis-config.xml文件
<?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>

    <!--引入外部properties文件以获取外部属性引用-->
    <properties resource="jdbc.properties"/>
    
	<!--自定义类型处理器-->
    <typeHandlers>
        <!--采用全局声明的方式对SexEnum类型使用自定义处理器-->
       <typeHandler handler="com.castle.handlers.SexHandler" javaType="com.castle.tools.SexEnum" jdbcType="INTEGER"/>
    </typeHandlers>
    
    <!--数据库环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${database.driver}"/>
                <property name="url" value="${database.url}"/>
                <property name="username" value="${database.username}"/>
                <property name="password" value="${database.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!--映射文件-->
    <mappers>
    	<!--注册先前编写的UserMapper.xml文件-->
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

解决方案2: 通过具体的Mapper映射xml配置文件中,直接显式指定数据库字段对应的java属性所需要使用的自定义转换器。

具体做法:修改UserMapper.xml文件
① 针对Select的SQL语句,可以使用resultMap属性来指定本xml文件中声明好的变量,如此处使用map1
② 针对Insert的SQL语句,由于没有resultMap属性,可以在插入的语句中,具体为VALUES()语句中对指定的Java的User类相应属性,使用typeHandler进行指定。如:#{sex, typeHandler=com.castle.handlers.SexHandler}
<?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.castle.mapper.UserMapper">

    <!--采用显示声明的方式为指定字段sex设置自定义处理器-->
    <resultMap id="map1" type="com.castle.POJO.User">
        <result property="id" column="id"/>
        <!--当使用user_name带下划线的名称时,会导致变量读取为null,解决办法为删去下划线即可-->
        <result property="userName" column="username"/>
        <result property="sex" column="sex" typeHandler="com.castle.handlers.SexHandler"/>
        <result property="mess" column="mess"/>
    </resultMap>

    <!--在编写SQL语句时,数据库字段必须对应好POJO类的相应属性,若不一致使用AS指定-->
    <select id="getUser" parameterType="long" resultType="com.castle.POJO.User" resultMap="map1">
        SELECT id, user_name AS userName, sex, mess FROM `user` WHERE id = #{id}
    </select>
    <insert id="insertUser" parameterType="com.castle.POJO.User">
        INSERT `user`(id, user_name, sex, mess) VALUES (#{id}, #{userName}, #{sex, typeHandler=com.castle.handlers.SexHandler}, #{mess})
    </insert>

</mapper>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值