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

Posted 新来的大狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于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>

以上是关于关于Mybatis中使用自定义类型通过 自定义TypeHandler类型处理器进行类型转换的两种配置方案-枚举类型示例的主要内容,如果未能解决你的问题,请参考以下文章

oracle 自定义函数,调用时报“程序包或函数无效”

mybatis自定义类型处理器

mybatis自定义类型处理器

MyBatis使用自定义TypeHandler转换类型

MyBatis使用自定义TypeHandler转换类型

自定义枚举 --- Swagger文档展示