如何在类级别约束之前validation字段级别约束?
我上课了:
@ColumnNameUnique(groups = CreateTableChecks.class) public class Table { @Valid @NotEmpty(groups = CreateTableChecks.class) private List measures; }
-
类级别约束
@ColumnNameUnique(groups = CreateTableChecks.class)
始终先运行,之后运行字段级约束@NotEmpty(groups = CreateTableChecks.class)
。 -
无论如何强制字段级约束
@NotEmpty(groups = CreateTableChecks.class)
先运行?
您需要使用@GroupSequence
并重新定义默认组序列 。 如果没有这个,组中的validation顺序就不会被定义,它可以是任何顺序(在你的情况下,总是首先执行类级别约束不是必须的)。 像这样的东西应该工作:
@GroupSequence({FieldChecks.class, ClassChecks.class}) @ColumnNameUnique(groups = ClassChecks.class) public class Table { @Valid @NotEmpty(groups = FieldChecks.class) private List measures; }
现在,如果validation了@Default
组,则首先validation类级别约束,然后validation字段级别约束。
您可以在Validator.validate
调用之前使用reflection手动validation字段,而不是使用@Hardy提到的@GroupSequence解决方案。
方法
你可以包装这个方法
/** * Validates all single constrained fields of the given object and returns a * set of {@link ConstraintViolation}. If
first
is *true
only the ConstraintViolation of the first invalid * constraint is returned.
* This method is useful to validate property constraints before class level * constraints. * * @param validator * @param object * @param first Set totrue
if only the exceptions of the first * invalid property shall be thrown * @param groups */ public static Set> validateProperties(final Validator validator, final Object object, final boolean first, final Class>... groups) { if (object == null) throw new IllegalArgumentException("object must not be null."); if (validator == null) throw new IllegalArgumentException("validator must not be null."); final Set > cvs = new HashSet<>(); forFields: for (final Field field : ReflectionUtils.getAllFields(object.getClass(), null)) { final Annotation[] annotations = field.getDeclaredAnnotations(); boolean hasValidAnnotation = false; for (final Annotation annotation : annotations) { // single Constraint final Constraint constraint = annotation.annotationType().getAnnotation(Constraint.class); if (constraint != null) { cvs.addAll(validator.validateProperty(object, field.getName(), groups)); if (!cvs.isEmpty() && first) break forFields; } if (annotation.annotationType().equals(Valid.class)) hasValidAnnotation = true; } // nested validation if (hasValidAnnotation) { field.setAccessible(true); Object value = null; try { value = field.get(object); } catch (IllegalArgumentException | IllegalAccessException e) { // log } if (value != null) { cvs.addAll(validateProperties(validator, value, first, groups)); if (!cvs.isEmpty() && first) break; } } } return cvs; } /** * Validates all single constrained fields of the given object and throws a * {@link ConstraintViolationException}. If first
is *true
only the ConstraintViolation of the first invalid * constraint is thrown.
*
* This method is useful to validate property constraints before class level * constraints. * * https://hibernate.atlassian.net/browse/BVAL-557 * * @see #validateProperty(Validator, Object, String, Class...) * * @param validator * @param object * @param first Set totrue
if only the exceptions of the first * invalid property shall be thrown * @param groups * * @throws ConstraintViolationException */ public static void validatePropertiesThrow(final Validator validator, final Object object, final boolean first, final Class>... groups) throws ConstraintViolationException { if (object == null) throw new IllegalArgumentException("object must not be null."); if (validator == null) throw new IllegalArgumentException("validator must not be null."); final Set> cvs = validateProperties(validator, object, first, groups); if (!cvs.isEmpty()) throw new ConstraintViolationException(cvs); }
我更喜欢这种方法,因为我不想用组序列注释更新所有实体和字段。
- 与Bean Validation API结合使用时,Hibernate不遵循JPA规范吗?
- 如何在ConstraintValidator中自动assembly服务
- Spring MVC – REST服务中bean列表上的@Valid
- Bean Validation Groupinheritance不适用于Group Sequence Provider
- 我可以在ConstraintValidator中为Method参数更改属性路径吗?
- 如何使用Spring MVC JSR-303 Validator将不同的模型类validation为一个表单
- BigDecimal的JPA @Size注释
- 如何获取ConstraintValidatorContext?
- JSR303自定义validation器被调用两次