protobuf 生成的 Java 对象上的级联 bean 验证不起作用

Posted

技术标签:

【中文标题】protobuf 生成的 Java 对象上的级联 bean 验证不起作用【英文标题】:Cascaded bean validation on protobuf generated Java object not working 【发布时间】:2021-11-10 16:06:45 【问题描述】:

我正在尝试使用 Bean Validation 来验证 protobuf 消息生成的 Java 对象。我正在使用Hibernate Validator's Programmatic constraint definition fluent API。它适用于直接对象字段(实际上我正在验证“getters”),但由于某种原因valid() 方法没有触发级联对象的验证。

我尝试创建常规 Java 对象(没有验证注释的 POJO,只有我正在测试的字段的 getter)并应用相同的 Hibernate 验证器约束映射 - 它可以正常工作。

您知道为什么这种方法不适用于从 protobuf 消息生成的 Java 对象吗?

// protobuf example
message Car 
  com.mycompany.Driver driver = 1;
  string manufacturer = 2;
  ...


message Driver 
  string name = 1;
  ...



// Java code
configuration.createConstraintMapping()
  .type(Car.class)
    .getter("driver")
      .valid()
    .getter("manufacturer")
      .constraint(new NotEmptyDef())

  .type(Driver.class)
    .getter("name")
      .constraint(new NotEmptyDef());

 ...

 Car car = new Car();
 car.setDriver(new Driver());

 validator.validate(car);
 // then - validation does not validate Driver object

【问题讨论】:

【参考方案1】:

一位同事发现了一个问题。我们不得不更改DefaultGetterPropertySelectionStrategy (link to documentation)。默认情况下,getter 方法被视为方法Object get*()boolean is*()boolean has*()。由于从 protobuf 生成的 Java 类包含 boolean has*() 来指示该属性是否可用 - 它被 Hibernate Validator 错误地用作有效的 getter 方法。

所以,解决方案是基于DefaultGetterPropertySelectionStrategy创建自定义getter方法策略,排除has*()。然后在创建Validator时注册为:

...
Validator validator = configuration.addMapping(configuration.createConstraintMapping())
                .getterPropertySelectionStrategy(new ProtobufGetterPropertySelectionStrategy())
                .buildValidatorFactory()
                .getValidator();

【讨论】:

以上是关于protobuf 生成的 Java 对象上的级联 bean 验证不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Ruby ActiveRecord 模型中的级联删除?

mybatis 级联

mybatis怎么有条件的级联查询????

同一张表之间多对多的级联删除

many2one的级联添加

one2many的级联保存