23

假设我有以下简单的 java bean:

class MyBean {
   private Date startDate;
   private Date endDate;
   //setter, getters etc...
}

JSR 303 中是否有一种机制来创建自定义验证器来验证 startDate 必须在 endDate 之前的约束?

在我看来,这是一个常见的用例,但我找不到这种多属性关系约束的任何示例。

4

5 回答 5

33

我可以想到一些可以尝试的方法。

您可以Constraint使用适当的验证器创建一个类型本身的目标:

@ValidateDateRange(start="startDate", end="endDate")
public class MyBean {

您可以将日期范围封装在类型中并验证:

public class DateRange {    
  private long start;
  private long end;

  public void setStart(Date start) {
    this.start = start.getTime();
  }

  // etc.

您可以添加一个执行检查的简单属性:

public class MyBean {
  private Date startDate;
  private Date endDate;

  @AssertTrue public boolean isValidRange() {
    // TODO: null checks
    return endDate.compareTo(startDate) >= 0;
  }
于 2009-11-09T13:01:56.673 回答
14

如果您在 4.1 或更高版本中使用Hibernate Validator ,则可以将@ScriptAssert约束与脚本或表达式语言一起使用来表达这种约束。使用 JavaScript,您的示例将如下所示:

 @ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")
 public class CalendarEvent {

      private Date startDate;

      private Date endDate;

      //...
 } 

您可以通过为您选择的脚本语言创建自定义约束来获得更紧凑的语法:

@JexlAssert("_.startDate < _.endDate")
public class CalendarEvent {

    private Date startDate;

    private Date endDate;

    //...
}
于 2011-02-04T21:22:52.907 回答
3

答案是类级别的验证器。您可以定义可以放置在实体类上的自定义约束。在验证时,您将整个实例传递给 isValid() 方法。然后,您可以将两个日期相互比较。另请参阅 Hibernate Validator文档

于 2009-11-09T14:00:49.813 回答
1

@AssertMethodAsTrue - 跨越多个属性的可重用约束注释。

于 2010-01-26T09:30:48.427 回答
-5

由于无法在 JSR 303 验证器中访问 bean,因此这是不可能的。

一种解决方法是提供您自己的ConstraintValidatorContext并通过对您当前正在验证的 bean 的引用来扩展它。但我不确定您是否可以修改/覆盖各自的工厂。

于 2009-11-09T11:13:55.847 回答