MyBatis Plus插入数据库表空值列报错问题,需要配置 jdbc-type-for-null 属性

场景:
在使用 mybatis 插入 oracle或mysql 数据库的数据列为空的时候,在Configuration类中初始化jdbcTypeForNull默认值是Other,这样就会报错

解决:

1、配置 jdbc-type-for-null 的属性值为 null,默认为 other

mybatis-plus:
  configuration:
    cache-enabled: false
    # 配置列空值类型 JdbcTypeForNull, oracle数据库必须配置。注意单引号,默认为other
    jdbc-type-for-null: 'null'
    # 打印出执行的sql语句,使用p6spy代理的时候不需要配置此项
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

注意:
1、jdbc-type-for-null 的值单引号是必须的
2、log-impl:输出执行的 sql 脚本信息

<think>好的,我现在需要帮助用户解决在MyBatis Plus中判断传入参数是否为空的最佳实践。首先,我需要回顾用户的问题和之前的对话历史。用户之前询问了如何区分两个List<Map<String, Object>>中的相同值和不同值,我给出了使用HashSet和自定义比较的方法,还提到了处理复杂类型和序列化的方案。现在用户的新问题是关于MyBatis Plus中参数是否为空的判断。 用户提供的引用内容中提到了MyBatis Plus配置、测试用例、批量删除以及自定义异常接口。其中,引用[1]展示了如何配置MybatisPlusInterceptor,引用[3]是测试用例,引用[4]讨论了批量操作和BatchExecutor,引用[5]涉及自定义异常。这些可能和参数判断有关联吗?比如,在配置拦截器时可能需要处理参数,或者在批量操作中需要检查参数是否为空以避免误。 用户的需求是判断传入参数是否为空的最佳实践。首先,我需要回忆MyBatis Plus的条件构造器QueryWrapper和UpdateWrapper,它们通常用于构建查询条件,其中可以判断字段是否为空。例如,使用isNull和isNotNull方法。此外,MyBatis Plus的注解@TableField可能也有策略来处理空值,比如在插入或更新时自动忽略空字段。 另外,用户可能在XML映射文件中使用动态SQL标签,如<if>,来根据参数是否为空决定是否包含某段SQL。例如,在update操作中,只更新非空的字段,避免将数据库中的现有值覆盖为null。同时,引用[4]中提到的批量删除和动态SQL拼接可能涉及参数非空判断,以防止SQL语句过大或参数为空导致的误。 还需要考虑自定义注解或拦截器的可能性。例如,通过自定义拦截器在SQL执行前检查参数,如果必填参数为空则抛出异常。引用[5]中的自定义异常接口BaseErrorInfoInterface可能在这里派上用场,可以定义参数为空的误码和描述。 同时,全局配置中的jdbcTypeForNull设置也很重要,当字段值为null时,MyBatis会如何处理。默认情况下,可能会转换为OTHER类型,但有些数据库不支持,需要明确指定为NULL。 此外,用户可能希望在不同操作(插入、更新、查询)中有不同的空值处理策略。例如,插入时忽略null字段,更新时同样忽略,而查询时可能需要将空参数作为查询条件的一部分。 需要综合这些方法,给出几种最佳实践,并说明适用场景。例如,使用条件构造器在服务层进行判断,或者在XML中使用动态SQL,或者利用注解配置策略。还要考虑代码的简洁性、维护性和性能影响。 最后,确保回答结构清晰,分步骤说明,并提供代码示例,如使用QueryWrapper的示例、XML中的<if>标签示例,以及全局配置的示例。同时,提醒用户注意jdbcTypeForNull配置,避免数据库兼容性问题,并建议结合自定义异常处理参数为空的情况,提升系统健壮性。</think>### MyBatis Plus 判断参数为空的最佳实践 在 MyBatis Plus 中判断参数是否为空可以通过以下方案实现,根据不同的场景选择合适的方法: --- #### 1. **使用条件构造器 `QueryWrapper/UpdateWrapper` 的链式方法** 适用于**动态构建查询条件**或**更新操作**时过滤空值。 ```java // 示例:查询 name 不为空且 age 大于 18 的记录 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper .eq(StringUtils.isNotBlank(name), "name", name) // 仅当 name 非空时生效 .gt(age != null, "age", age); List<User> users = userMapper.selectList(queryWrapper); ``` - **`eq(condition, column, value)`**:当 `condition=true` 时添加条件 - **优势**:链式语法简洁,支持空值过滤和复杂逻辑组合[^1] --- #### 2. **XML 映射文件中使用动态 SQL 标签** 适用于**复杂 SQL 逻辑**或需要**复用 SQL 片段**的场景。 ```xml <!-- 示例:根据参数动态更新非空字段 --> <update id="updateUser" parameterType="User"> UPDATE user <set> <if test="name != null and name != ''">name = #{name},</if> <if test="age != null">age = #{age},</if> </set> WHERE id = #{id} </update> ``` - **`<if>` 标签**:通过 OGNL 达式判断参数是否为空 - **注意**:避免 SQL 注入,优先使用 `#{}` 占位符[^2] --- #### 3. **全局配置空值处理策略** 通过 MyBatis Plus 的全局配置,控制**插入/更新操作中空值的处理方式**: ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加空值处理策略(需自定义拦截器或使用已有策略) return interceptor; } } ``` - **字段策略注解**:在实体类字段上使用 `@TableField` ```java public class User { @TableField(insertStrategy = FieldStrategy.NOT_EMPTY) private String name; // 插入时仅当 name 非空才包含该字段 } ``` - **策略选项**: - `FieldStrategy.NOT_NULL`:非 null 时更新 - `FieldStrategy.NOT_EMPTY`:非空(如 String 类型还需非空字符串)[^3] --- #### 4. **自定义注解或拦截器校验参数** 适用于**强制校验必填参数**的业务场景: ```java // 自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface RequiredParam { } // AOP 拦截器 @Aspect @Component public class ParamCheckAspect { @Before("@annotation(requiredParam)") public void checkParam(JoinPoint joinPoint, RequiredParam requiredParam) { Object[] args = joinPoint.getArgs(); for (Object arg : args) { if (arg == null || (arg instanceof String && ((String) arg).isEmpty())) { throw new BusinessException("参数不能为空"); // 引用自定义异常接口[^5] } } } } ``` --- #### 5. **处理 JDBC 类型与空值兼容性** 在 `application.yml` 中配置 `jdbcTypeForNull`,避免数据库驱动不兼容: ```yaml mybatis: configuration: jdbc-type-for-null: null # 明确指定 null 值的 JDBC 类型 ``` --- ### 方案对比 | 方法 | 适用场景 | 优点 | 缺点 | |---------------------|----------------------------|--------------------------|-----------------------| | 条件构造器 | 简单查询/更新 | 代码简洁,链式调用 | 复杂 SQL 支持有限 | | XML 动态 SQL | 复杂业务逻辑 | 灵活,支持复用 SQL 片段 | 需维护 XML 文件 | | 全局字段策略 | 统一控制空值行为 | 配置简单,减少重复代码 | 无法覆盖所有特殊场景 | | 自定义校验 | 强制参数校验 | 业务逻辑与数据层解耦 | 增加代码复杂度 | --- ### 推荐实践 1. **优先使用条件构造器**处理简单空值逻辑(如查询过滤) 2. **复杂业务逻辑**使用 XML 动态 SQL 标签(如多关联更新) 3. **关键参数**通过自定义注解+AOP拦截器强制校验(如支付接口的金额字段)[^5] 4. 全局配置 `jdbcTypeForNull` 避免数据库兼容性问题[^4] --- ### 示例代码 ```java // 使用条件构造器实现动态更新 public void updateUserIfNotNull(User user) { UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper .set(user.getName() != null, "name", user.getName()) .set(user.getAge() != null, "age", user.getAge()) .eq("id", user.getId()); userMapper.update(null, updateWrapper); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值