java - 如何为同一个属性节点添加多个约束违规?
问题描述
我有一个习惯ConstraintValidator
。我想要做的是为同一个属性节点添加多个约束违规,使用相同的消息和不同的动态有效负载。这可能吗?
自定义注释:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CustomFieldConstraintValidator.class)
public @interface CustomFieldConstraint {
String message() default "message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
自定义约束验证器:
public class CustomFieldConstraintValidator implements ConstraintValidator<CustomFieldConstraint, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
var valid = true;
var hibernateConstraintValidatorContext = context.unwrap(HibernateConstraintValidatorContext.class);
hibernateConstraintValidatorContext.disableDefaultConstraintViolation();
if (value > 0) {
valid = false;
hibernateConstraintValidatorContext.withDynamicPayload(Map.of("must_be_less_than", 0))
.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate())
.addPropertyNode("field")
.addConstraintViolation();
}
if (value > 5) {
valid = false;
hibernateConstraintValidatorContext.withDynamicPayload(Map.of("must_be_less_than", 5))
.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate())
.addPropertyNode("field")
.addConstraintViolation();
}
return valid;
}
}
验证器测试:
public class HibernateValidatorTest {
private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
@Test
void multipleFailuresForSameField() {
var foo = new Foo(10);
var constraintViolations = validator.validate(foo);
assertEquals(2, constraintViolations.size());
}
public static class Foo {
@CustomFieldConstraint
private int field;
public Foo(int field) {
this.field = field;
}
}
}
测试失败了expected: <2> but was: <1>
。
解决方案
您遇到此问题是因为ConstraintViolation
作为集合返回,并且根据设计,动态有效负载不包含在equals()
方法中。请参阅https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java#L251。
因此,您的 2 个约束在 Set 级别被视为相等。
您需要改变做事的方式,并使用这两种信息来丰富有效负载。
推荐阅读
- tcl - 如何在 TCL 中设置符号链接的 mtime?
- css - 在heroku上的react + rails应用程序中CSS未导入JS文件
- newrelic - Fluentd NewRelic 输出“时间必须是 Fluent::EventTime (or Integer): Float”
- python - NoReverseMatch:未找到带有参数 '('',)' 的“RPA_tool”的反向。尝试了 1 种模式:['admin_tool/RPA_tool/(?P
[^/]+)/$'] - android - React 原生轨道播放器中的应用启动问题
- r - 从 data.table 中的每个组中减去一个向量,并在两者中按日期匹配
- html - 如何将 div 放在居中的 div 上?
- reactjs - 在 React 中使用 map 将四个元素传递到一个组件中
- javascript - 如何在不使用表单的情况下从 Django Post 请求中获取文件对象并将其保存到模型中?
- html - 当内部呈现的列表增长时,如何防止具有绝对位置的 div 容器被切断?