Java 从isValid()方法调用其他验证器?

Java 从isValid()方法调用其他验证器?,java,bean-validation,Java,Bean Validation,假设我有以下场景: public class EntityA { private List<EntityB> listOfBs; } 公共类实体a{ 私人名单; } 只有在某个验证组下运行时,我才尝试将验证级联到Bs列表。因此,理想情况下,这: public class EntityA { @Valid(groups = {SomeSpecificGroup.class}) private List<EntityB> listOfBs; } 公共类

假设我有以下场景:

public class EntityA {
   private List<EntityB> listOfBs;
}
公共类实体a{
私人名单;
}
只有在某个验证组下运行时,我才尝试将验证级联到Bs列表。因此,理想情况下,这:

public class EntityA {
   @Valid(groups = {SomeSpecificGroup.class})
   private List<EntityB> listOfBs;
}
公共类实体a{
@有效(组={SomeSpecificGroup.class})
私人名单;
}
很遗憾,@Valid没有groups()属性。所以我想我应该试试这样:

@Constraint(validatedBy = { CascadedValidator.class })
@Target({ ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CascadedValidation {
    Class<?>[] groups() default { };
}
@Constraint(validatedBy={CascadedValidator.class})
@目标({ElementType.METHOD,ElementType.FIELD})
@保留(RetentionPolicy.RUNTIME)
公共@接口级联验证{
类[]组()默认值{};
}
并编写一个验证器(CascadedValidator),激活后将执行级联(=将验证其上放置的集合的所有元素)。 我的问题是如何执行级联验证? 到目前为止,我有:

public class CascadedValidator implements ConstraintValidator<CascadedValidation, Object>{
    private Class<?>[] groups;

    @Override public void initialize(CascadedValidation constraintAnnotation) {
        groups = constraintAnnotation.groups();
    }

    @Override public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null || !(value instanceof Iterable)) {
            return true;
        }
        for (Object item : (Iterable)value) {
            //validate item using the groups?!
        }
    }
}
public类CascadedValidator实现ConstraintValidator{
私有类[]组;
@重写公共void初始化(级联验证约束){
groups=constraintanotation.groups();
}
@重写公共布尔值isValid(对象值、ConstraintValidatorContext上下文){
if(value==null | |!(Iterable的值instanceof)){
返回true;
}
对于(对象项:(Iterable)值){
//使用组验证项目?!
}
}
}
我知道我可以通过创建另一个“内联”验证器来实现实际验证:

Validator Validator=Validation.buildDefaultValidatorFactory().getValidator();
设置违规行为;
if(决策分类(组)){
对于(对象项:(Iterable)值){
if(groups!=null&&groups.length>0){
违规=验证程序。验证(项目、组);
}否则{
违规=验证程序。验证(项目);
}
如果(!inflictions.isEmpty()){
返回false;
}
}
}
返回true;
但这对我来说很难闻。 当然有一种理智的/正常的/简单的方法可以做到这一点

编辑-实际用例


我的API接受EntityA(它有一个B列表)和EntityB作为顶级实体(因此您可以直接发送单个B)。A和B都有一个id属性,但我只需要提交的顶级对象上的非空id。因此,如果服务得到一个A,其中包含一个idea和几个“空白”B,则可以,但如果我得到一个B作为顶级参数,则它必须有一个id。

您不应该从
约束验证器
实现中调用验证引擎

如果您使用的是BeanValidation1.1,那么可以看看哪一个可以让您控制在级联验证时传播的验证组。例如,您可以执行以下操作:

@Valid
@ConvertGroup(from = Default.class, to = SomeSpecificGroup.class)
private List<EntityB> listOfBs;
@有效
@ConvertGroup(from=Default.class,to=SomeSpecificGroup.class)
私人名单;

当你说“不应该”时,这是明确禁止的还是纯粹的丑陋?我也不能使用convertgroup。我已经详细阐述了我上面的问题来解释原因。我不想以某种方式“旋转”级联,我想阻止它,尽管它没有被明确禁止,但它是一个潜在的性能问题(至少如果您创建了一个新的验证程序工厂,需要再次建立约束元模型)b)如果模型中存在双向关系,并且您使用的是
@Valid
(单个验证器需要确保它可以防止无限循环),那么您可能会遇到无限循环。也就是说,我认为您实际上可以使用
@ConvertGroup
,只需将
Default
转换为级联成员上的任何其他组。B中的
@NotNull
约束在顶级时将被验证,但在从A导航时不会验证。
@Valid
@ConvertGroup(from = Default.class, to = SomeSpecificGroup.class)
private List<EntityB> listOfBs;