MyBatis更新List类型字段报错,如何修复Type java.util.ArrayList不支持问题?
解决MyBatis更新时List参数TypeHandler不生效问题
问题场景
现有策略表结构、自定义TypeHandler、Mapper接口及XML配置,savePolicy方法执行正常,但调用updateVersionAndStatements时抛出Type java.util.ArrayList not supported type异常,错误栈显示MyBatis使用了默认的ObjectTypeHandler处理List参数,导致数据库驱动无法识别该类型。
原因分析
savePolicy传入的是Policy对象,statements作为对象属性,MyBatis能通过属性的泛型类型List<PolicyStatement>匹配到自定义TypeHandler。updateVersionAndStatements直接传入独立的List<PolicyStatement>参数,由于Java泛型擦除机制,运行时MyBatis仅能识别参数为List(甚至被识别为Object),无法精准匹配到处理List<PolicyStatement>的自定义TypeHandler,因此触发默认类型处理器,导致驱动报错。
修复方案
方案一:在Mapper XML中显式指定TypeHandler
修改updateVersionAndStatements的SQL语句,为statements参数指定对应的TypeHandler:
<update id="updateVersionAndStatements"> UPDATE policy SET statements = #{statements, typeHandler=io.github.ctlove0523.toyiam.server.model.storage.handler.PolicyStatementsHandler},version = #{version} WHERE id = #{id} </update>
通过显式指定,强制MyBatis使用自定义TypeHandler处理该参数。
方案二:优化TypeHandler的注解配置
在PolicyStatementsHandler类上添加注解,明确声明其处理的Java类型和JDBC类型:
import org.apache.ibatis.annotations.MappedJdbcTypes; import org.apache.ibatis.annotations.MappedTypes; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; @MappedTypes(List.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class PolicyStatementsHandler extends BaseTypeHandler<List<PolicyStatement>> { // 原有实现代码保持不变 }
配合MyBatis配置文件中已有的TypeHandler注册,让MyBatis在遇到List类型参数时优先使用该自定义处理器。
方案三:将更新参数封装为对象
创建参数封装类,统一传递更新所需字段:
public class PolicyUpdateParam { private String id; private String version; private List<PolicyStatement> statements; // 生成getter、setter方法 }
修改Mapper接口和XML:
public interface PolicyMapper { // 其他方法不变 void updateVersionAndStatements(PolicyUpdateParam param); }
<update id="updateVersionAndStatements" parameterType="PolicyUpdateParam"> UPDATE policy SET statements = #{statements},version = #{version} WHERE id = #{id} </update>
这种方式与savePolicy的参数传递逻辑一致,MyBatis能通过对象属性的泛型类型自动匹配到自定义TypeHandler。
内容的提问来源于stack exchange,提问作者TongChen
相关产品推荐
相关产品推荐

