You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot中为Java实体类添加基于条件的@NotNull约束?

刚好之前做过类似的需求!要实现这种当firstName不为空时,lastName必须必填的条件约束,咱们得借助Hibernate Validator的自定义校验能力来实现,毕竟标准的Bean Validation注解没法直接处理这种字段间的依赖校验。下面一步步来:

1. 定义自定义校验注解

首先创建一个作用在类上的注解,用来标记需要做这种条件校验的实体:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.TYPE}) // 因为要校验类内多个字段的关系,所以作用在类上
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RequireLastNameValidator.class) // 指定对应的校验逻辑实现类
public @interface RequireLastNameWhenFirstNamePresent {
    // 校验失败时的默认提示信息
    String message() default "当firstName不为空时,lastName不能为空";
    
    // 分组校验用,默认空数组即可
    Class<?>[] groups() default {};
    
    // 负载信息,用于传递额外校验元数据,默认空数组
    Class<? extends Payload>[] payload() default {};
}
2. 实现校验器的核心逻辑

接下来写注解对应的校验器,实现ConstraintValidator接口,这里我们直接校验整个User对象的字段关系:

import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class RequireLastNameValidator implements ConstraintValidator<RequireLastNameWhenFirstNamePresent, User> {

    @Override
    public void initialize(RequireLastNameWhenFirstNamePresent constraintAnnotation) {
        // 初始化逻辑,这里不需要额外操作
    }

    @Override
    public boolean isValid(User user, ConstraintValidatorContext context) {
        // 核心判断逻辑:如果firstName有有效内容(非空非空白),则lastName必须也有有效内容
        if (StringUtils.hasText(user.getFirstName())) {
            return StringUtils.hasText(user.getLastName());
        }
        // 如果firstName为空,不管lastName是什么都通过校验
        return true;
    }
}

这里用了Spring的StringUtils.hasText()来判断字符串是否非空且不是纯空白,如果你没用Spring,也可以自己写判断逻辑:firstName != null && !firstName.trim().isEmpty()。

3. 在实体类上应用自定义注解

最后把这个注解加到你的User类上就可以了:

@Entity
@RequireLastNameWhenFirstNamePresent // 加上自定义条件校验注解
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "user_id")
    private Integer userId;
    
    @Column(name = "firstName")
    private String firstName;
    
    @Column(name = "lastName")
    private String lastName;
    
    // 别忘了添加getter和setter,校验器需要访问这些字段
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
4. 触发校验的常用方式

要让这个校验生效,你需要在需要校验的地方加上@Valid或者@Validated注解:

  • Controller层接收请求时自动校验:
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
    userRepository.save(user);
    return ResponseEntity.ok(user);
}
  • 服务层手动调用校验器:
@Autowired
private Validator validator;

public void saveUser(User user) {
    Set<ConstraintViolation<User>> violations = validator.validate(user);
    if (!violations.isEmpty()) {
        throw new ConstraintViolationException(violations);
    }
    userRepository.save(user);
}

这样就完美实现了你要的需求:只有当firstName不为空时,lastName才会被校验是否非空~

内容的提问来源于stack exchange,提问作者parthivrshah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:08:48