Mybatis自定义类型转换器Typehandler

需求:
一个商户,在登记的时候需要注册它的经营范围。比如1手机,2电脑,3相机,4平板,在界面上是一个复选框(checkbox)。
在数据库保存的是用逗号分隔的字符串,例如“1,3,4”,而返回给程序的时候是整形数组List {1,3,4}。很显然,mybatis默认提供的类型转换器达不到这样的要求,这种情况下,我们可以自定义mybatis的类型转换器就可以实现自定义 Java类型与数据库类型之间的自动转换
实现:
自定义一个TypeHandler,在对数据库时进行入库操作时,将List 类型的数据自动转换为逗号分隔的字符串进行入库,在查询时,自动再转换为List进行返回,

  • 数据库定义
CREATE TABLE `merchant` (
  `id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `scope` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

  • merchant POJO:
package com.gupaoedu.domain;

import lombok.Data;
import java.util.List;

@Data
public class Merchant {
    private int id;
    private String name;
    private List<Integer> scope;
}
  • 自定义typeHandler
    自定义的typeHandler或者是mybatis默认的typeHandler,都会去继承一个基类BaseTypeHandler<>, 其中的泛型是我们要处理的Java类型,需要重写四个方法:

setNonNullParameter: 设置String类型的参数时调用, 从Java类型到Jdbc类型的转换,只有在insert语句中的字段上加上typehandler=自定义的typeHandler全类名,才会生效

getNullableResult(ResultSet resultSet, String s) : 根据列名获取String 类型的参数时调用,从数据库查询出Jdbc类型,把它赋值给Java类型时会调用,是Jdbc类型 -》 Java类型

getNullableResult(CallableStatement callableStatement, int i) 根据参数索引获取

package com.gupaoedu.type;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MerchantHandler extends BaseTypeHandler<List<Integer>> {


    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<Integer> integers, JdbcType jdbcType) throws SQLException {
	StringBuffer sb = new StringBuffer();
        integers.forEach(integer -> {
            sb.append(String.valueOf(integer)).append(",");
        });
        preparedStatement.setString(i, sb.substring(0, sb.length() - 1));
    }

    @Override
    public List<Integer> getNullableResult(ResultSet resultSet, String s) throws SQLException {
        if(null == resultSet.getString(s) || 0 == resultSet.getString(s).trim().length()){
            return null;
        }
        String[] split= resultSet.getString(s).split(",");
        List<Integer> list= new ArrayList<>();
        for (String str : split) {
            list.add(Integer.valueOf(str));
        }
        return list;
    }

    @Override
    public List<Integer> getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return null;
    }

    @Override
    public List<Integer> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return null;
    }
}
  • mapper接口和xml
package com.gupaoedu.mapper;

import com.gupaoedu.domain.Merchant;
import org.apache.ibatis.annotations.Param;

public interface MerchantMapper {
    Merchant getMerchantById(@Param("id") int id);
   int insertMerchant(Merchant merchant);
 }



<mapper namespace="com.gupaoedu.mapper.MerchantMapper">
      <resultMap id="merchantMap" type="com.gupaoedu.domain.Merchant">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="scope" column="scope" jdbcType="VARCHAR"
                javaType="list" typeHandler="com.gupaoedu.type.MerchantHandler"/>
    resultMap>

    <select id="getMerchantById" resultMap="merchantMap">
		select * from merchant where id = #{id}
	select>
<insert id="insertMerchant" parameterType="com.gupaoedu.domain.Merchant">
       INSERT INTO merchant(name, scope)VALUES
       ( #{name},#{scope,typeHandler=com.gupaoedu.type.MerchantHandler,jdbcType=VARCHAR})
    insert>
mapper>
  • mybatis全局配置添加:
 <typeHandlers>
        <typeHandler jdbcType="VARCHAR" javaType="list" handler="com.gupaoedu.type.MerchantHandler"/>
    typeHandlers>
 <mappers>
        <mapper resource="BlogMapper.xml"/>
        <mapper resource="BlogMapperExt.xml"/>
        <mapper resource="MerchantMapper.xml"/>
    mappers>
  • 测试类
package com.gupaoedu;

import com.gupaoedu.domain.Merchant;
import com.gupaoedu.mapper.MerchantMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class MyTypeHandlerTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void prepare() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        inputStream.close();
    }

    @Test
    public void getMerchantByIdTest(){
        SqlSession sqlSession = null;
        try {
            sqlSession = sqlSessionFactory.openSession();
            MerchantMapper mapper = sqlSession.getMapper(MerchantMapper.class);
            Merchant merchant = mapper.getMerchantById(1);
            System.out.println(merchant);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            sqlSession.close();
        }
    }
  @Test
    public void insertMerchant(){
        Merchant merchant = new Merchant();
        merchant.setName("gupaoedu");
        List<Integer> scope = Arrays.asList(new Integer[]{1,2,3,4});
        merchant.setScope(scope);
        SqlSession sqlSession = null;
        try {
   
            sqlSession = sqlSessionFactory.openSession();
            MerchantMapper mapper = sqlSession.getMapper(MerchantMapper.class);
           int rowAffected = mapper.insertMerchant(merchant);
           // 这里需要手动提交才可以!SqlSession的默认实现DefaultSqlSession中的openSession方法,默认设置的autoCommit是false!!!
            sqlSession.commit();
            System.out.println(rowAffected);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            sqlSession.close();
        }
    }	

}

  • 测试结果
    Mybatis自定义类型转换器Typehandler_第1张图片

Mybatis自定义类型转换器Typehandler_第2张图片
在插入操作中,忘记了事务提交操作,导致每次看到数据库执行了插入操作,然后又被自动回滚了,查看sqlSessionFactory.openSession()的实现,发现openSession方法默认是关闭了自动提交事务的
Mybatis自定义类型转换器Typehandler_第3张图片

你可能感兴趣的:(Mybatis)