【问题标题】:"Dynamic" java validation framework?“动态”java验证框架?
【发布时间】:2010-05-19 09:01:03
【问题描述】:

AFAIK JSR-303 是标准的 bean 验证系统。

我不知道它是否可以做这样的验证(我猜不能):

  • 如果对象设置了已删除标志,则无法修改该对象
  • 您无法更改开始日期属性,日期已过
  • 您不能减少 bean 中的某些整数属性

那么我该如何处理取决于对象先前状态的验证呢?

我想在hibernate3.5 - spring3 - JPA2环境中解决类似的问题。

谢谢


我的解决方案是弄乱休眠,重新加载对象以查看旧状态(在驱逐新对象之后)。这次我需要一些更聪明的解决方案...

【问题讨论】:

  • “object has a deleted flag set”是什么意思?
  • 假设您不想真正删除任何对象,因为偏执狂(并且出于记录目的),而是创建了一个布尔标志。如果你删除一个对象,只会设置已删除的标志...

标签: java hibernate bean-validation


【解决方案1】:

我认为这不能使用 JSR 303 验证(或我使用过的任何其他验证框架)来完成。验证通常是无状态的——你将一个对象的实例传递给它,你的验证框架会测试以确保你的对象的当前值是有效的。对对象以前的状态没有真正的了解。

您可以做到这一点 - 只是不需要验证。您可以使用constrained property,也可以使用代理模式或 AOP 来完成这项工作。

【讨论】:

  • 谢谢,只有当约束只影响一个属性时,受约束的属性才合适(顺便说一句,在我的所有示例中,但这是一个限制......)
【解决方案2】:

听起来您想要验证的字段(关于以前的状态)都是关于记录的元数据,而不是真实数据。所有这些字段(idDeleted、createdDate 等)最好不要放在您的领域层之外,因此不需要验证。我会将确定和设置这些值的逻辑放在你的数据访问层中,这样使用你的存储库接口的系统就不需要知道或关心它们是否正确。

如果我对这些字段是元数据的假设不正确,并且您有用户输入的数据,其验证取决于先前的状态,那么我认为对先前值的额外查找是荒谬的,不应该被淘汰的问题。在你的情况下这是有道理的。 Hibernate 本身在 then hood 下进行查找以确定在使用它的保存功能时是插入还是更新。

希望您能找到合理的解决方案。

【讨论】:

    【解决方案3】:

    如何处理取决于对象先前状态的验证?

    我不是 100% 确定它是否可行,但我能想到的唯一方法是创建一个由“新状态”和“旧状态”(瞬态)组成的对象图并验证对象图作为一个整体使用自定义约束。这至少是我会尝试的。

    【讨论】:

      【解决方案4】:

      我可能会创建一个瞬态字段,表示先前版本,它指向代表其先前状态的数据副本。此对象是在构造时创建的,但由于它被标记为瞬态,因此未序列化。然后对其进行验证。

      最简单的实现是添加一个名为 makeACopy() 的方法,该方法制作对象的副本并将其放入字段中。

      您可以通过实现 Clonable 或创建一个可以进行反射的实用程序类来增加复杂性,但这取决于您。我建议 makeACopy() 并稍后重构,因为它更容易考虑。

      【讨论】:

        【解决方案5】:

        我也不知道任何现成的解决方案。您怀疑 JSR-303 无法完成这项工作,因为它的验证是“静态的”。

        但是……

        一个想法是使用一些 AOP 技术来做到这一点。所以...

        如果对象设置了已删除标志,则不能修改该对象

        我将实现这个作为在每个 setter 周围注册的代理方法。代理方法将检查“已删除”标志。如果设置为true,则会抛出异常,否则会执行原来的方法。

        您无法更改开始日期属性,日期已过

        这个很相似。这次您不会访问拦截的 setter 中的任何其他属性,而是访问字段和 setter 参数的原始(尚未更改)值。

        你不能减少 bean 中的一些整数属性

        这与日期相同,唯一的区别是日期类型(日期与整数)。

        人们可能会争论 AOP 是否是这个任务的好选择,但仍然是一个解决方案。我也很怀疑。

        还有一个问题是,我猜您可能希望对 JPA 实体实施这些限制。所以使用Spring AOP 不会那么容易,因为实体不会由 Spring 管理。

        【讨论】:

          【解决方案6】:

          一种完全不同的方法是将验证检查放入属性的设置器中。缺点是你会失去声明性。

          例子:

          public void setCounter(int newCounter) {
              if (newCounter < this.counter) {
                 throw new IllegalOperationException("Cannot decrease the counter");
              } else {
                 this.counter = newCounter;
              }
          }
          

          【讨论】:

          • 你应该以正确的顺序设置你的属性(想想规则,验证更多的属性),否则你的逻辑会崩溃......
          【解决方案7】:

          您可能想查看OVal。我们一直在做这种验证。通常,它是使用 SimpleCheck 完成的,您可以在其中获取对象和值,并且可以进行各种交叉检查。

          【讨论】:

            猜你喜欢
            • 2010-09-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-08
            • 1970-01-01
            • 2017-04-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多