首页 > 其他分享 >mybatis之typeHandler

mybatis之typeHandler

时间:2023-02-01 11:13:33浏览次数:40  
标签:java typeHandler ibatis apache 3.5 mybatis org

背景:

业务系统,多个选项(字符串数组,List),要存储到数据库中,数据表用的是 VARCHAR。
于是需要一种转换,
使用到的是 mybatis, 于是就使用 mybatis 的 typeHandler

代码

1、定义一个 typeHandler

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

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

/**
 * mybatis-数组与字符串转换的handler
 */
@MappedTypes({List.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class StringListTypeHandler extends BaseTypeHandler<List> {
    @Override
    public List getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        return getStringArray(rs.getString(columnName));
    }

    @Override
    public List getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        return this.getStringArray(rs.getString(columnIndex));
    }

    @Override
    public List getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        return this.getStringArray(cs.getString(columnIndex));
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i,
                                    List parameter, JdbcType jdbcType) throws SQLException {
        //由于BaseTypeHandler中已经把parameter为null的情况做了处理,所以这里我们就不用再判断parameter是否为空了,直接用就可以了
        StringBuffer result = new StringBuffer();
        for (Object value : parameter) {
            result.append(value).append(",");
        }
        result.deleteCharAt(result.length()-1);
        ps.setString(i, result.toString());
    }

    private List getStringArray(String columnValue) {
        if (columnValue == null)
            return null;
        return Arrays.asList(columnValue.split(","));
    }
}


然后去声明一下这个 typeHandler

<typeHandlers>
    <typeHandler handler="com.carrot.demo.mybatis.handler.StringListTypeHandler"/>
</typeHandlers>

mapper 接口是这样传参数的

    int updateByRecordId(@Param("recordId")String recordId, @Param("instances")List<String> instances);

然后,
要注意的是,在查询和写入(更新,新增)在对应的字段上都要指定这个字段对应的typeHandler

    <resultMap id="BaseResultMap" type="com.carrot.demo.mybatis.entity.RecordInstance">
        <result column="record_id" jdbcType="VARCHAR" property="recordId"/>
        <result column="instances_info" jdbcType="VARCHAR" property="instances" typeHandler="com.carrot.demo.mybatis.handler.StringListTypeHandler"/>
    </resultMap>

    // 这个要注意的是,update / insert 的时候,也要指定这个字段绑定这个 handler, 不然的话,就会报错
    // 会报一个 Not support this type 的错误(见报错详情)
    <update id="updateByRecordId">
        UPDATE record_instances SET instances_info = #{instances,jdbcType=VARCHAR,typeHandler="com.carrot.demo.mybatis.handler.StringListTypeHandler}
        WHERE record_id = #{recordId,jdbcType=VARCHAR}
    </update>

报错详情

Caused by: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType VARCHAR . Try setting a different JdbcType for this parameter or a different configuration property. Cause: dm.jdbc.driver.DMException: Not support this type
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:75) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:67) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:73) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:94) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:88) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.7.jar:3.5.7]
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.5.7.jar:3.5.7]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_261]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_261]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_261]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_261]
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64) ~[mybatis-3.5.7.jar:3.5.7]
	at com.sun.proxy.$Proxy196.update(Unknown Source) ~[?:?]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194) ~[mybatis-3.5.7.jar:3.5.7]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_261]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_261]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_261]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_261]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433) ~[mybatis-spring-1.3.1.jar:1.3.1]
	... 28 more

所以除了查询的时候要绑定,写入的时侯也要指定一下,不然肯定会造成类型不匹配的错误。因为传参一个List, 但sql是用一个 varchar 去接收,是不行的。

标签:java,typeHandler,ibatis,apache,3.5,mybatis,org
From: https://www.cnblogs.com/aaacarrot/p/17081934.html

相关文章