MyBatis中空字符串转为null问题咨询:非空字段异常排查
MyBatis中空字符串被转为null的原因及解决办法
我来帮你拆解这个问题,这类情况在使用MyBatis自动生成的Example类时挺常见的,咱们先理清楚原因,再给出针对性的解决办法:
问题原因
- 默认类型处理器的行为:MyBatis默认使用的
org.apache.ibatis.type.StringTypeHandler,在处理空字符串时,会默认将其转换为null值。当你把空字符串传入Example的条件方法(比如andAppVersionEqualTo)时,这个类型处理器会悄悄把空字符串换成null。 - MyBatis Generator的默认配置:如果是用MyBatis Generator生成的XXExample类,默认开启了
trimStrings属性(值为true),它会自动去除字符串两端的空格,要是原字符串就是空字符串,处理后就会变成null。 - Example动态SQL生成逻辑:自动生成的Example类在构建SQL时,会对传入的参数做校验,空字符串可能会被判定为“无效值”,进而被替换成null参与SQL生成。
解决办法
1. 自定义String类型处理器(推荐)
创建一个自定义的类型处理器,覆盖默认的StringTypeHandler,让它保留空字符串:
import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class NonNullStringTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { // 直接传入空字符串,不转为null ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } }
然后在MyBatis配置文件中注册这个处理器:
<typeHandlers> <typeHandler handler="com.yourpackage.handler.NonNullStringTypeHandler" javaType="java.lang.String"/> </typeHandlers>
2. 修改MyBatis Generator配置
如果是用Generator生成的Example类,在generatorConfig.xml里关闭trimStrings属性,避免空字符串被处理成null:
<javaModelGenerator targetPackage="com.yourpackage.model" targetProject="src/main/java"> <!-- 关闭字符串自动修剪,保留空字符串 --> <property name="trimStrings" value="false"/> </javaModelGenerator>
修改后重新生成XXExample类即可生效。
3. 代码层面手动规避
在设置Example条件前,手动确保空字符串能被正确传入:
XXExample example = new XXExample(); XXExample.Criteria criteria = example.createCriteria(); String appVersion = ""; // 直接传入空字符串,不做额外判断(前提是类型处理器或Generator配置已调整) criteria.andAppVersionEqualTo(appVersion);
如果不想全局调整,也可以针对这个字段单独处理,比如空字符串时改用andAppVersionIsNotNull配合其他条件,但这种方式比较繁琐,适合临时场景。
4. 调整MyBatis全局配置
在mybatis-config.xml中设置jdbcTypeForNull为VARCHAR,让MyBatis在处理空值时以字符串类型传入:
<settings> <setting name="jdbcTypeForNull" value="VARCHAR"/> </settings>
这个设置主要针对null值,但也能间接避免空字符串被强制转为null后引发的数据库非空约束报错。
内容的提问来源于stack exchange,提问作者Kenny Qiao
相关产品推荐
相关产品推荐

