3

AFAIK JSR-303 is the standard bean validation system.

I don't know whether it could do validations like this (I guess no):

  • if an object has a deleted flag set, you cannot modify the object
  • you cannot change the start date property, after the date is passed
  • you cannot decrease some integer properties in the bean

So how can I handle validations, which depend on the previous state of an object?

I would like to solve problems like that in hibernate3.5 - spring3 - JPA2 environment.

Thanks


My solution was to mess with hibernate, reload the object to see the old state (after evicting the new object). This time I need some smarter solution...

4

7 回答 7

2

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

你可以做到这一点 - 只是没有验证。您可以使用受约束的属性,或者您可以使用代理模式或 AOP 来完成这项工作。

于 2010-05-19T13:41:24.913 回答
1

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

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

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

于 2010-05-27T21:10:15.783 回答
0

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

但...

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

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

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

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

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

您不能减少 bean 中的某些整数属性

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

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

另一个担忧是,我猜您可能希望对 JPA 实体强制执行这些限制。所以使用Spring AOP不会那么容易,因为实体不会由 Spring 管理。

于 2010-05-27T21:20:09.200 回答
0

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

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

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

于 2010-05-22T00:38:27.167 回答
0

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

于 2010-08-06T10:54:37.983 回答
0

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

例子:

public void setCounter(int newCounter) {
    if (newCounter < this.counter) {
       throw new IllegalOperationException("Cannot decrease the counter");
    } else {
       this.counter = newCounter;
    }
}
于 2010-05-27T21:23:17.163 回答
0

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

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

于 2010-05-19T14:47:25.810 回答