Tutorial for using TypeHandler in MyBatis

1. The role of TypeHandler and its usage scenarios

When we usually develop and operate databases, querying, inserting data and other operations, sometimes data type mismatch exceptions are reported, and we can know that the data type is not unique and must be a variety of different data types. And we must be clear that java, as a programming language, has its own data types, and databases also have their own data types.

jdbc data type: org.apache.ibatis.type.JdbcType This enumeration is all database support types

Java data types: int, long, string, ...

Be sure to distinguish, for example, java-heavy date data is inserted into the database, it should have been converted into a certain type of database, and it must have nothing to do with java. There are some operations that we can't see in the middle that do data processing.

Assuming that the java type at this time is the same as the database data type, how should the date data in other languages ​​be interpreted when it is inserted into the database, for example, C# operates the database input time type, and C# must have nothing to do with java. So there is a data type relationship between each language and the database.

think:

Because java and the database have their own data types, we cannot see whether there are other operations before storing the java data in the database. Otherwise, how does the java data know which jdbc data type it matches?

Answer: The mybatis framework makes a default relationship correspondence for each data type, and all implementation classes of BaseTypeHandler are here to do these processes.

For example: what type of jdbc is the date in java when it is inserted into the database, and why is it this type? What is the specific operation in the middle?

Answer: DateTypeHandler is to solve the processing of date data type.

2. Use of TypeHandler

When we want to customize the data type conversion between Java and JDBC, we need to implement the TypeHandler interface. The source code of this interface is as follows:

//此接口作用是用于指定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;
}

If it is necessary to convert the list field to varchar before inserting it into the database, that is, list [1,2,3] == "varchar 1,2,3, and automatically convert from the list type when loading from the database to the program, the implementation code is as follows :

1. Write the typehandler implementation class and formulate conversion rules

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. Configure the mybatis xml file

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

3. Write 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 code

    @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();
    }

Test Results:

query data test varchar --> list conversion::

    @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]]
 */
    }

3. TypeHandlers registration method

  1. Single registration: the typeHandler tag specifies the full class name of the handler

  1. Multiple registrations: specify multiple single registration methods; or use the package tag

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

Guess you like

Origin blog.csdn.net/w20001118/article/details/128703641