JAVA

Mybatis什么时候需要添加“jdbcType=数据类型”

在执行SQL时MyBatis会自动通过对象中的属性给SQL中参数赋值,它会自动将Java类型转换成数据库的类型。而一旦传入的是null它就无法准确判断这个类型应该是什么,就有可能将类型转换错误,从而报错。所以我们这样做。

疑问来自于,有时候Mapper.xml中,下面都可以用。

id = #{id,jdbcType=INTEGER}

id = #{id}

那么问题来了!

Mybatis中什么时候应该声明jdbcType?

一般情况下,两种写法都可以。它们都可以获取Dao层传递过来的参数。
但是,当传入的参数为null时,需要指定jdbcType的类型,否则mybatis无法解析。

#{property, jdbcType=VARCHAR}
如果一个列允许 null 值,并且会传递值 null 的参数,就必须要指定 JDBC Type

如果是一个可以为null的字段,在insert的时候,没有给该字段赋值,mybatis就会报下面的错误

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='__frch_item_0.defaultValue', mode=IN, javaType=class java.lang.String, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #6 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 无效的列类型: 1111
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
 
Caused by: org.apache.ibatis.type.TypeException: Error setting null for parameter #6 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: java.sql.SQLException: 无效的列类型: 1111
	at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:47)
	at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)
	... 54 more
Caused by: java.sql.SQLException: 无效的列类型: 1111

当Mybatis不能自动识别你传入对象的类型时。

所以要解决这个问题,需要针对这些可能为空的字段,手动指定其转换时用到的类型。

一般情况下,我们没有必要按个字段去识别/判断它是否可以为空,而是将所有的字段都当做可以为空,全部手动设置转换类型。

<update id="updateByPrimaryKey" parameterType="com.funyan.User" >    
update user    
set user_name = #{userName,jdbcType=VARCHAR},    
user_pass = #{userPass,jdbcType=VARCHAR},    
user_nickname = #{userNickname,jdbcType=VARCHAR},    
user_email = #{userEmail,jdbcType=VARCHAR},    
user_url = #{userUrl,jdbcType=VARCHAR},    
user_avatar = #{userAvatar,jdbcType=VARCHAR},    
user_last_login_ip = #{userLastLoginIp,jdbcType=VARCHAR},    
user_register_time = #{userRegisterTime,jdbcType=TIMESTAMP},    
user_last_login_time = #{userLastLoginTime,jdbcType=TIMESTAMP},    
user_status = #{userStatus,jdbcType=INTEGER}    
where user_id = #{userId,jdbcType=INTEGER}    
</update>

附:Mybatis中 javaType 和 jdbcType 对应关系

JDBCType            JavaType
CHAR                String
VARCHAR             String
LONGVARCHAR         String
NUMERIC             java.math.BigDecimal
DECIMAL             java.math.BigDecimal
BIT                 boolean
BOOLEAN             boolean
TINYINT             byte
SMALLINT            short
INTEGER             int
BIGINT              long
REAL                float
FLOAT               double
DOUBLE              double
BINARY              byte[]
VARBINARY           byte[]
LONGVARBINARY               byte[]
DATE                java.sql.Date
TIME                java.sql.Time
TIMESTAMP           java.sql.Timestamp
CLOB                Clob
BLOB                Blob
ARRAY               Array
DISTINCT            mapping of underlying type
STRUCT              Struct
REF                 Ref
DATALINK            java.net.URL