根据错误日志 java.lang.IllegalArgumentException: argument type mismatch
,问题集中在 方法返回值的类型与实际数据库查询结果类型不匹配。我们逐步分析并解决该问题。
使用_byte[]
解决了问题,这是因为 MyBatis 对 BLOB 类型的默认映射行为 和 Java 类型推断 的细节有一些特殊处理。让我们深入分析为什么这样做会解决问题。
错误:
<select id="getFlowabledImg" resultType="byte[]">
select BYTES_ from act_ge_bytearray where ID_ = #{id}
</select>
正确:
<select id="getFlowabledImg" resultType="_byte[]">
select BYTES_ from act_ge_bytearray where ID_ = #{id}
</select>
- 问题根源:MyBatis 的 resultType 默认映射
当 MyBatis 查询返回 BLOB 类型时,它依赖于 JDBC 驱动和 MyBatis 的默认类型处理器(TypeHandler)来将结果映射到 Java 类型。
问题发生的原因: 在你的原始配置中,可能使用了 byte[],而 MyBatis 对 BLOB 类型的默认映射行为无法准确将 BLOB 数据映射到 byte[],导致类型不匹配。
_byte[] 的作用: _byte[] 是 MyBatis 的一种内置别名,用于显式告诉 MyBatis 直接将结果映射为 byte[],绕过不必要的类型推断。
定义 _byte[]:
alias: _byte[] = byte[]
因此,MyBatis 在使用 _byte[] 时会直接将 BLOB 映射为 byte[],避免了类型猜测错误。
-
类型推断的潜在问题
使用 byte[] 或 resultType=“byte[]” 时,MyBatis 的行为可能会受到以下因素影响:
MyBatis 默认类型映射机制:
如果你没有显式指定 resultType 或映射规则,MyBatis 可能会尝试用 Object 接受查询结果。
查询返回 BLOB 时,MyBatis 需要依赖驱动的 ResultSet.getBlob() 方法,而不同的驱动行为可能不一致,可能返回 Blob 对象,而不是直接的 byte[]。
MyBatis-Plus 的封装: MyBatis-Plus 在内部对结果进行了进一步的处理(比如调用了 convertToArray 方法),这使得类型映射更加严格。如果类型不匹配,会导致 java.lang.IllegalArgumentException: argument type mismatch。 -
_byte[] 的解决方式
显式使用 _byte[] 通知 MyBatis 直接将结果映射为 byte[],跳过了潜在的类型转换问题,避免了 MyBatis 的以下行为:
自动类型推断(如返回 Blob)。
类型处理器(TypeHandler)尝试将 BLOB 转换为其他对象。 -
JDBC 驱动与类型映射的关系
BLOB 映射行为: 不同 JDBC 驱动对 BLOB 的处理可能不同。例如:
某些驱动可能直接返回 byte[]。
某些驱动返回 Blob 对象,需要显式调用 Blob.getBytes() 才能转换为 byte[]。
MyBatis 默认行为: 当 MyBatis 检测到 BLOB 类型时,会根据 JDBC 驱动返回值尝试进行转换。如果驱动返回 Blob,但方法返回值期望 byte[],就会报错。 -
总结:为什么 _byte[] 能解决问题
_byte[] 是 MyBatis 的内置别名,显式告知 MyBatis 使用 byte[] 作为结果类型。
避免了 MyBatis 类型推断和 JDBC 驱动之间的不一致。
绕过了 MyBatis-Plus 对返回结果封装时的类型检查。
因此,使用 _byte[] 更明确地定义了结果类型,解决了类型映射问题。