使用Java Hibernate验证列表项的子集,获取完整的属性路径

使用Java Hibernate验证列表项的子集,获取完整的属性路径,java,spring-boot,hibernate-validator,Java,Spring Boot,Hibernate Validator,我正在使用javax和hibernate创建我的第一个springbootweb应用程序,以验证从JSP表单输入的数据。我有一个预订模型,其中包括一系列行程模型: @ValidBooking(groups = {BookingI.class}) public class Booking { @Min(value = 1, groups = {BookingI.class, Default.class}) private int totalJourneys; @Valid pri

我正在使用javax和hibernate创建我的第一个springbootweb应用程序,以验证从JSP表单输入的数据。我有一个预订模型,其中包括一系列行程模型:

@ValidBooking(groups = {BookingI.class})
public class Booking {

  @Min(value = 1, groups = {BookingI.class, Default.class})
  private int totalJourneys;
  @Valid
  private List<Journey> journeys;
  // relevant getters and setters
上面的代码适用于我的测试,但是当使用jsp表单呈现时,spring数据绑定失败,因为违规约束的属性路径返回为“locations[0]”,而不是预期的“booking.journies[0].locations[0]”

是否有人对如何返回完整的属性路径有任何建议,或者提供更好的解决方案

提前谢谢


Java 8、javax验证api 2.0.1、hibernate validator 6.0.7

首先,有几点意见:

  • 在验证器中构建
    验证器工厂
    不是一个好主意。这是一个非常沉重的对象,每次验证它时都需要构建
    旅程
    bean的元数据,速度会很慢
  • 要构建约束,您需要构建精确的路径,即使用
    inContainer()
    atIndex()
    。。。不能简单地将
    toString()
    传递给属性
当然,你可以解决后者,但前者绝对是不可能的

有一些东西你可以试试:


  • 创建一个
    JourneyDefaultGroupSequenceProvider
    ,该程序实现
    DefaultGroupSequenceProvider
    ,当它是要验证的对象时返回有效组,当不想验证旅程时,返回未在任何约束中使用的某个随机组<代码>列表感谢@GuillaumeSmet的回复和建议,我正在实施GroupSequenceProvider。我唯一的问题是,我是否可以访问旅程GroupSequenceProvider中的父对象信息(在本例中为Booking),以便识别旅程对象的索引位置是否小于Booking.totalJourneys值?您只有一个实例,其中有
    @GroupSequenceProvider
    。因此,不幸的是,您需要一个指向对象中父对象的链接。我创建了一个更明显的东西。将在其中添加有关索引的案例,但我不确定找到解决方案是否容易。
    @ValidJourney
    public class Journey {
    
      @Valid
      private List<Location> locations;
      private List<String> dates;
      private List<String> times;
    
      // relevant getters and setters
    
    public class ValidBookingValidator implements ConstraintValidator<ValidBooking, Booking> {
    
      @Override
      public boolean isValid(Booking booking, ConstraintValidatorContext constraintValidatorContext) {
    
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
    
        int totalJourneys = booking.getTotalJourneys();
        int validJourneys = 0;
        for (int journeyIdx = 0; journeyIdx < totalJourneys; journeyIdx++) {
            Set<ConstraintViolation<Journey>> journeyConstraintViolations = validator.validate(booking.getJourneys().get(journeyIdx));
    
            if (journeyConstraintViolations.isEmpty()) {
                validJourneys++;
            } else {
                for (ConstraintViolation<Journey> violation : journeyConstraintViolations) {
                    constraintValidatorContext.buildConstraintViolationWithTemplate(violation.getMessage())
                    .addPropertyNode(violation.getPropertyPath().toString())
                    .addConstraintViolation();
                }
            }
        }
        return totalJourneys == validJourneys;
      }
    
    }
    
    @GroupSequenceProvider(JourneyDefaultGroupSequenceProvider.class)
    public class Journey {
        // ...
    }