MyBatis中TypeHandler的使用教程

一.TypeHandler作用及其使用场景

在我们平常开发操作数据库时,查询、插入数据等操作行为,有时会报数据类型不匹配异常,就可以得知数据的类型是不唯一的必然是多种不同的数据类型。并且我们必须要明确的一点就是java作为一门编程语言有自己的数据类型,数据库也是有自己的数据类型的。

jdbc数据类型:org.apache.ibatis.type.JdbcType 此枚举就是所有的数据库支持类型

java数据类型:int、long、string、…

一定要分清,例如java重的date数据插入到数据库中,应该是已经转换成了数据库的某种类型,必然跟java已经没有关系了。中间有一些我们看不见的操作做了数据处理。

假设此时的java类型与数据库数据类型是一样的,哪么其他语言中的日期数据插入数据库时又该怎么解释,例如C#操作数据库存入时间类型,C#与java肯定没有关系吧。所以每种语言与数据库之间有种数据类型关系对应。

思考:

因为java与数据库各自有数据类型,所以在将java数据存入数据库前中间是否有其他操作,是我们看不见的,不然java数据怎么知道自己与哪个jdbc数据类型匹配?

答:mybatis框架为每种数据类型做了默认的关系对应,BaseTypeHandler的所有实现类,就是来做这些处理的。

例如:java中的date插入数据库时是jdbc哪种类型,怎么就是这种类型? 中间具体有什么操作?

答:DateTypeHandler就是来解决date数据类型的处理。

二.TypeHandler使用

我们想要自定义去处理Java和JDBC的数据类型转换时,需要实现TypeHandler接口,该接口源码如下:

//此接口作用是用于指定jdbc与java的数据类型间对应关系处理。
public interface TypeHandler<T> {
  // 保存操作,数据入库之前时数据处理
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  //下面三个则是,从数据库加载数据后,vo对象封装前的数据处理
  T getResult(ResultSet rs, String columnName) throws SQLException;
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

假如现在需要将list字段插入到数据库前转换成varchar,即list [1,2,3] ==》varchar 1,2,3,并且从数据库中加载到程序时自动转换从list类型,实现代码如下:

1.编写typehandler实现类,制定转换规则

package com.cjy.mybatis.typehandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.apache.log4j.Logger;

@MappedJdbcTypes(JdbcType.VARCHAR)  //数据库类型
@MappedTypes({List.class})            //java数据类型
public class ListTypeHandler implements TypeHandler<List<String>>{

    private Logger logger = Logger.getLogger(ListTypeHandler.class);
    
    @Override
    public void setParameter(PreparedStatement ps, int i,
            List<String> parameter, JdbcType jdbcType) throws SQLException {
        logger.info("method ====>>> setParameter");
        String hobbys = dealListToOneStr(parameter);
        ps.setString(i , hobbys);
    }

    /**
     * 集合拼接字符串
     * @param parameter
     * @return
     */
    private String dealListToOneStr(List<String> parameter){
        if(parameter == null || parameter.size() <=0)
            return null;
        String res = "";
        for (int i = 0 ;i < parameter.size(); i++) {
            if(i == parameter.size()-1){
                res+=parameter.get(i);
                return res;
            }
            res+=parameter.get(i)+",";
        }
        return null;
    }
    //
    @Override
    public List<String> getResult(ResultSet rs, String columnName)
            throws SQLException {
        logger.info("method ====>>> getResult(ResultSet rs, String columnName)");
        return Arrays.asList(rs.getString(columnName).split(","));
    }

    @Override
    public List<String> getResult(ResultSet rs, int columnIndex)
            throws SQLException {
        logger.info("method ====>>> getResult(ResultSet rs, int columnIndex)");
          return Arrays.asList(rs.getString(columnIndex).split(","));
    }

    @Override
    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException{
        logger.info("method ====>>> getResult(CallableStatement cs, int columnIndex)");
        String hobbys = cs.getString(columnIndex);
        return Arrays.asList(hobbys.split(","));
    }
}

2.配置mybatis xml文件

<typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>

3.编写sql

  <select id="selectEmp" resultType="com.cjy.mybatis.entity.Employee" parameterType="int">
    select id,user_name userName,gender,email,hobbys,createtime from employee where id = #{id}
  </select>
  
  <insert id="saveEmpOne" parameterType="com.cjy.mybatis.entity.Employee" >
  <!-- or parameterMap="parameMap" -->
      INSERT INTO employee(user_name,gender,email,createtime,hobbys) 
      VALUES(#{userName},#{gender},#{email},#{createtime,typeHandler=com.cjy.mybatis.typehandler.MyDateTypeHandler},
      #{hobbys,typeHandler=com.cjy.mybatis.typehandler.ListTypeHandler})
      <!--数据插入前:对hobbys做数据格式转换。  -->
  </insert>

4.测试代码

    @Test
    public void test2(){
        SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
         Employee employee = new Employee(null, "yanjiu", "1", "[email protected]", new Date(),Arrays.asList(new String[]{"yuwen","shuxue","yingyu","zhengzhi"}));
         EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
         int saveEmpOne = mapper.saveEmpOne(employee);
         System.out.println(saveEmpOne+"-------------------");
         openSession.commit();
         openSession.close();
    }

测试结果:

查询数据测试varchar–》list 转换::

    @Test
    public void test5(){
        SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
         EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
         Employee selectEmp = mapper.selectEmp(10);
         System.out.println(selectEmp);
/**数据加载成功
2019-07-24 15:08:02 INFO  com.cjy.mybatis.typehandler.ListTypeHandler - method ====>>> getResult(ResultSet rs, String columnName)
2019-07-24 15:08:02 INFO  com.cjy.mybatis.typehandler.MyDateTypeHandler - getResult(ResultSet rs, String columnName)....
Employee [id=10, userName=yanjiu, gender=1, [email protected], createtime=Wed Jul 24 15:05:58 CST 2019, hobbys=[yuwen, shuxue, yingyu, zhengzhi]]
 */
    }

三.typeHandlers注册方式

  1. 单个注册:typeHandler 标签指定handler 全类名

  1. 多个注册:指定多个单个注册方式;或者使用package 标签

  <typeHandlers>
         <!-- <typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>
         <typeHandler javaType="Date" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.MyDateTypeHandler"/> -->
         <package name="com.cjy.mybatis.typehandler"/>
         <!--
         typeHandler: 单个注册方式
         package:多个注册方式
           -->
  </typeHandlers>

猜你喜欢

转载自blog.csdn.net/w20001118/article/details/128703641
今日推荐