Java JSR303-应用按顺序定义的所有验证组

Java JSR303-应用按顺序定义的所有验证组,java,spring,bean-validation,hibernate-validator,Java,Spring,Bean Validation,Hibernate Validator,我想对一个bean进行条件验证。为此,我定义了一个DefaultGroupSequenceProvider,它返回要验证的组列表 现在,当验证序列中多个组中违反约束的对象时,只有第一个失败的组返回结果。我希望在所有违规行为上都得到一个错误,而不仅仅是第一组中的失败 我认为这不需要代码示例,但如果我错了,我很乐意提供一个 我在创建序列时遵循了这一点。如果有必要,我们使用弹簧 请注意,这是有效的,因为不可能将无效的bean报告为有效的。但是,如果用户有一些输入打破了3个约束,我返回了2个失败,那么在

我想对一个bean进行条件验证。为此,我定义了一个
DefaultGroupSequenceProvider
,它返回要验证的组列表

现在,当验证序列中多个组中违反约束的对象时,只有第一个失败的组返回结果。我希望在所有违规行为上都得到一个错误,而不仅仅是第一组中的失败

我认为这不需要代码示例,但如果我错了,我很乐意提供一个

我在创建序列时遵循了这一点。如果有必要,我们使用弹簧

请注意,这是有效的,因为不可能将无效的bean报告为有效的。但是,如果用户有一些输入打破了3个约束,我返回了2个失败,那么在第一个字段被纠正后,用户将在最后一个字段中得到另一个失败。不完全是用户友好的

例如:

豆子

枚举类型

public enum MyType {
    FIRST, SECOND
}
提供者

public class BeanSequenceProvider implements DefaultGroupSequenceProvider<MyBean> {
    @Override
    public List<Class<?>> getValidationGroups(final MyBean object) {
        final List<Class<?>> classes = new ArrayList<>();

        classes.add(MyBean.class);

        if (object != null && object.getType() == MyType.SECOND) {
            classes.add(Special.class);
        }

        return classes;
    }
测试班

public class MyBeanTest {

    private static Validator validator;

    private MyBean objectUnderTest;

    @BeforeClass
    public static void setUpOnce() throws Exception {
        final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

        validator = validatorFactory.getValidator();
    }

    @Before
    public void setUp() throws Exception {
        objectUnderTest = new MyBean();

        objectUnderTest.setName("Simen");
        objectUnderTest.setType(MyType.FIRST);
        objectUnderTest.setLastName("Woop");
    }

    @Test
    public void testValid() throws Exception {
        assertThat(validator.validate(objectUnderTest), is(empty()));
    }

    @Test
    public void testMissingName() throws Exception {
        objectUnderTest.setName(null);

        assertThat(validator.validate(objectUnderTest), hasSize(1));
    }

    @Test
    public void testMissingLastName() throws Exception {
        objectUnderTest.setLastName(null);

        assertThat(validator.validate(objectUnderTest), is(empty()));

        objectUnderTest.setType(MyType.SECOND);

        assertThat(validator.validate(objectUnderTest), hasSize(1));

        objectUnderTest.setName(null);

        assertThat(validator.validate(objectUnderTest), hasSize(2));
    }

最后一个断言失败了,因为有一个违规,而不是两个。由于默认组中违反了约束,因此未违反
特殊组。

好的,现在我理解了您的问题。答案是,如果给定组中存在一个或多个冲突,验证将停止。引用规范:

第4.6节“验证程序”中定义了处理组; 如果序列中处理的一个组生成一个或多个 违反约束时,序列中的组不得 被处理。这样可以确保仅计算一组约束 如果另一组约束有效


在您的情况下,
Default
组中存在冲突,这意味着
特殊
组永远不会被验证。

我从未处理过这个问题,但也许您应该使用
DefaultGroupSequenceProvider
以外的其他工具?基本上你的意思是你不想让错误按顺序返回,所以使用其他方法?这是我的想法,但我的谷歌搜索没有给我任何选择。有什么想法吗?嗯。。您为
GroupSequenceProvider
选择的原因是什么?我必须获取正在验证的实例,因为应该验证哪些组取决于该对象上枚举的值。我的谷歌搜索让我找到了我在描述中提供的链接,只要所有违规行为都针对同一个群体,这个链接就有效。好吧,我想我无法回答这个问题。我把它添加到我的收藏夹中,希望有人能接管它。祝你好运!是的,我知道,但我想得到所有团体的所有违规行为,而不是短路验证。你知道我有什么办法可以做到吗?我并不特别受当前实现的约束,这正是我进行条件验证的方式。
public interface Special {
}
public class MyBeanTest {

    private static Validator validator;

    private MyBean objectUnderTest;

    @BeforeClass
    public static void setUpOnce() throws Exception {
        final ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

        validator = validatorFactory.getValidator();
    }

    @Before
    public void setUp() throws Exception {
        objectUnderTest = new MyBean();

        objectUnderTest.setName("Simen");
        objectUnderTest.setType(MyType.FIRST);
        objectUnderTest.setLastName("Woop");
    }

    @Test
    public void testValid() throws Exception {
        assertThat(validator.validate(objectUnderTest), is(empty()));
    }

    @Test
    public void testMissingName() throws Exception {
        objectUnderTest.setName(null);

        assertThat(validator.validate(objectUnderTest), hasSize(1));
    }

    @Test
    public void testMissingLastName() throws Exception {
        objectUnderTest.setLastName(null);

        assertThat(validator.validate(objectUnderTest), is(empty()));

        objectUnderTest.setType(MyType.SECOND);

        assertThat(validator.validate(objectUnderTest), hasSize(1));

        objectUnderTest.setName(null);

        assertThat(validator.validate(objectUnderTest), hasSize(2));
    }