如何在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
相关产品推荐
相关产品推荐

