java - 当 beanType 是接口(interface)时 Validator.validateValue 忽略验证(hibernate-validator-6.0.18)

标签 java hibernate validation

我创建了一个库,其中仅包含对域对象建模的接口(interface)。这些接口(interface)具有我想要测试的(类、属性、方法和构造函数级别)约束。

例如:

public interface User {
    @NotNull
    @Email
    String getEmail();
}

我想测试约束是否得到正确应用,所以我编写了一些测试。然而,我得到了意想不到的行为。

class UserTest {
    @Test
    void thisTestFails() {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<User>> violations = validator.validateValue(User.class, "email", null);
        assertEquals(1, violations.size());
    }

    @Test
    void thisTestPasses() {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<UserImpl>> violations = validator.validateValue(UserImpl.class, "email", null);
        assertEquals(1, violations.size());
    }

    private static class UserImpl implements User {
        @Override
        public String getEmail() {
            return null;
        }
    }
} 

当为 Class<T> beanType 提供参数时,Hibernate 完全忽略验证是一个接口(interface)。 我不想创建具体的类只是为了测试这些接口(interface)。这是 Hibernate 中的预期行为还是错误?

最佳答案

这是预期的行为。 Bean 验证规范定义可以在接口(interface)或类中定义约束,但验证的是遵循 Java Beans 约定的属性状态。

接口(interface)可以定义由类实现的 getter 方法,但它本身没有属性。

这是规范的相关部分:

5.1.1. Object validation

Constraint declarations can be applied to a class or an interface. Applying a constraint to a class or interface expresses a validation over the state of the class or the class implementing the interface.

5.1.2. Field and property validation

Constraint declarations can be applied on both fields and properties for the same object type. The same constraint should however not be duplicated between a field and its associated property (the constraint validation would be applied twice). It is recommended for objects holding constraint declarations to adhere to a single state access strategy (either annotated fields or properties).

When a field is annotated with a constraint declaration, field access strategy is used to access the state validated by such constraint.

When a property is annotated with a constraint declaration, property access strategy is used to access the state validated by such constraint.

确实,validateValue 方法不需要实例,因此理论上它可以测试接口(interface)的约束。但请注意 class 参数,它是一个 beanType,并且 bean 的类型需要是一个类,因为接口(interface)没有构造函数。

请注意与 Validator 中的方法 getConstraintsForClass 的区别,该方法明确声明可以获得接口(interface)上声明的约束:

class or interface type evaluated

validateValue的类参数:

the bean type

关于java - 当 beanType 是接口(interface)时 Validator.validateValue 忽略验证(hibernate-validator-6.0.18),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60514567/

相关文章:

java - 通过执行一个简单的 Spring Hibernate 集成程序,我遇到了以下问题

java - Hibernate 无法区分同名的列

java - @Scheduled @Transactional lazy init 集合错误 - 没有代理

php - 翻译 Woocommerce 中的结帐字段验证错误通知

java - Java (Android) 中的 List<?> 是什么?

java - 在 javafx 中删除边框 Pane 中的特定节点

asp.net-mvc - 使用 viewmodel 时的 asp.net mvc 验证

ruby-on-rails - 在数据库中实现 Ruby on Rails 验证规则而不是在模型文件中进行硬编码?

java - 如何从 Java 中的 TrainValidationSplitModel 中提取最佳参数集?

使用 Web 服务通过 SOAP 发送超过 12 MB 的数据时发生 Java 堆空间错误