AFAIK JSR-303是标准的bean验证系统。
我不知道它是否可以做这样的验证(我猜不是):
那么如何处理依赖于对象先前状态的验证呢?
我想在hibernate3.5 - spring3 - JPA2环境中解决类似的问题。
由于
我的解决方案是搞乱hibernate,重新加载对象以查看旧状态(在驱逐新对象之后)。这次我需要一些更智能的解决方案......
答案 0 :(得分:2)
我认为这不能使用JSR 303验证(或我使用的任何其他验证框架)来完成。验证通常是无状态的 - 您将其传递给对象的实例,并且验证框架会测试事物以确保对象的当前值有效。对该对象的先前状态没有真正的了解。
你可以这样做 - 只是没有验证。您可以使用constrained property,也可以使用代理模式或AOP来完成此工作。
答案 1 :(得分:1)
听起来您要验证的字段(关于先前状态)是关于记录的所有元数据,而不是真实数据。所有这些字段(idDeleted,createdDate等)最好不在您的域层中,因此不需要验证。我会把逻辑确定为&在数据访问层中设置这些值,以便使用存储库接口的系统不需要知道或关心如何正确使用它们。
如果我对这些字段的假设是元数据不正确并且您有用户输入的数据,验证取决于以前的状态,那么我认为对以前的值的额外查找是荒谬的,不应该出来这个问题。在你的情况下这是有道理的。 Hibernate本身在查找引擎时进行查找,以确定在使用它的保存函数时是INSERT还是UPDATE。
希望您找到合理的解决方案。
答案 2 :(得分:0)
如何处理验证,验证取决于对象的先前状态?
我不是100%确定它是可行的,但我能想到的唯一方法是创建一个由“新状态”和“旧状态”(瞬态)组成的对象图并验证对象图整体上使用自定义约束。至少这是我会尝试的。
答案 3 :(得分:0)
我可能会创建一个瞬态字段,表示以前的版本,它指向代表其先前状态的数据副本。此对象是在构造时创建的,但由于它被标记为瞬态,因此不会序列化。然后对它进行验证。
最简单的实现是添加一个名为makeACopy()的方法,该方法生成对象的副本并将其放入字段中。
您可以通过实现Clonable或创建可以进行反射的实用程序类来增加复杂性,但这取决于您。我建议makeACopy()稍后重构,因为它更容易思考。
答案 4 :(得分:0)
我也不知道任何现成的解决方案。因为你怀疑JSR-303不能完成这项工作,因为它的验证是“静态的”。
但是...
一个想法是使用一些AOP技术来做到这一点。所以......
如果对象设置了已删除的标志,则无法修改对象
这个我将实现作为在每个setter周围注册的代理方法。代理方法将检查'已删除'标志。如果设置为true,则抛出异常,否则将执行原始方法。
在传递日期后,您无法更改开始日期属性
这个是类似的。这次你不会访问截获的setter中的任何其他属性,而是访问field和setter参数的原始(尚未更改)值。
你不能减少bean中的一些整数属性
那个与日期相同,唯一的区别是日期类型(日期与整数)。
有人可以说AOP是否是这项任务的好选择,但仍然是一个解决方案。我也很怀疑。
还有一个问题是,我猜你想要在JPA实体上强制执行这些约束。所以使用Spring AOP并不那么容易,因为实体不会被Spring管理。
答案 5 :(得分:0)
完全不同的方法是将验证检查放入属性的设置器中。缺点是你会失去陈述性。
示例:
public void setCounter(int newCounter) {
if (newCounter < this.counter) {
throw new IllegalOperationException("Cannot decrease the counter");
} else {
this.counter = newCounter;
}
}
答案 6 :(得分:0)
您可能希望查看OVal。我们一直在做这种验证。通常情况下,使用SimpleCheck完成,您可以获得对象和值,并可以进行各种交叉检查。