有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

hibernate“动态”java验证框架?

AFAIKJSR-303是标准的bean验证系统

我不知道它是否可以像这样进行验证(我想没有):

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

那么,如何处理依赖于对象先前状态的验证呢

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

谢谢


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


共 (6) 个答案

  1. # 1 楼答案

    另一种完全不同的方法是将验证检查放入属性的setter中。缺点是你会失去陈述性

    例如:

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

    听起来,您想要验证的字段(关于以前的状态)都是关于记录的元数据,而不是真实数据。所有这些字段(idDeleted、createdDate等)最好不在域层中,因此不需要验证。我会提出确定&;在数据访问层中设置这些值,以便使用存储库接口的系统不需要知道或关心如何正确设置这些值

    如果我关于这些字段是元数据的假设不正确,并且用户输入的数据验证取决于以前的状态,那么我不认为额外查找以前的值是荒谬的,也不应该是不可能的。这对你来说是有道理的。Hibernate本身在then hood下进行查找,以确定在使用其save函数时是插入还是更新

    希望你能找到一个合理的解决方案

  3. # 3 楼答案

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

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

  4. # 4 楼答案

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

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

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

  5. # 5 楼答案

    我不认为使用JSR303验证(或我使用过的任何其他验证框架)可以做到这一点。验证通常是无状态的——您向它传递一个对象的实例,并且您的验证框架会进行测试,以确保对象的当前值是有效的。没有关于对象先前状态的真实知识

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

  6. # 6 楼答案

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

    但是

    一个想法是使用一些AOP技术来实现这一点。所以

    if an object has a deleted flag set, you cannot modify the object

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

    you cannot change the start date property, after the date is passed

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

    you cannot decrease some integer properties in the bean

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

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

    还有一个问题是,我想你会希望在JPA实体上强制执行这些约束。因此,使用Spring AOP并不是那么容易,因为实体不是Spring管理的