背景:
业务系统,多个选项(字符串数组,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