3

我们遇到了一个问题,我们必须维护一个日期字段 - 并且最好保留它的值 - 其中日期字段取决于其他实体的状态。用 JPA2 + Hibernate + Spring 解决这个问题的正确方法是什么?

基本上,我们有三个实体,我们称它们Parent为 、ChildConfdependentDate由依赖于其他实体状态的复杂业务规则计算得出。具体来说,应该Parent#date减去Conf#delay跳过周末或节假日的所有日子(持久数据)。

问题是每当Parent#date发生变化时,所有孩子的dependentDates 都应该重新计算。每当Child对象conf更改时,这也应该发生。目前,有一种基于Child对象关系计算新日期的服务方法(我们称之为calculateDate())。

我们面临着应该在哪里计算字段值的问题。我想出了三个可能的解决方案。其中哪一个 - 或者可能是其他东西 - 是更新依赖于其他实体状态的实体字段的首选方式?

  1. 一个 JPAEntityListener
    • 这在 JPA2 规范中是不鼓励的,因为 EntityListeners 不应该访问其他实体
    • 该字段将始终正确
  2. 更新的 Spring AOP 方面
    • 逻辑隐藏在其他类中,不容易看到
    • 切入点无法捕获所有持久/更新事件的风险
  3. 每个开发者为自己
    • 总是,当更新父类或子类的实例时,开发人员必须记住调用服务的calculateDate()方法
    • 这应该在dao还是服务层?
    • 开发者忘记添加调用,导致错误状态的风险

以下示例显示了省略注释配置的实体关系。

实体

public class Parent {
     LocalDate date;
     Set<Child> children;     // one-to-many
}

public class Conf {
     int delay;
}

public class Child {
     LocalDate dependentDate;
     Conf conf;               // many-to-one
     Parent parent;           // many-to-one
}
4

2 回答 2

2

依赖于多个实体状态的复杂业务规则属于服务层。应用程序中不应该有太多地方更改父母的日期和孩子的 conf,因此您不应该有太多地方必须进行新的日期计算。

如果你真的有很多地方可以这样做,你可以清楚地表明必须通过将 ChildDateUpdater 实例(ChildDateUpdater 是一个接口)传递给父日期的设置器和子 conf 的设置器来重新计算日期。这很明显,每次更改这两个字段时都必须做一些事情:

在父项中:

public void setDate(Date date, ChildDateUpdater childDateUpdater) {
    this.date = date;
    for (Child child : children) {
        childDateUpdater.updateChildDate(child);
    }
}

在儿童中:

public void setConf(Conf conf, ChildDateUpdater childDateUpdater) {
    this.conf = conf;
    childDateUpdater.updateChildDate(this);
}
于 2012-11-23T09:15:46.453 回答
0

将您的数据访问封装在 DAO 中。当Parent要保存 a 时,检查它的值是否有任何更改,如果是,则相应地更新子级。

的触发选项realsim也是可行的(基本上这是在不同级别实现的相同想法),但是您将失去可移植性(并且还会出现已加载的子项实例未更新的问题)。

于 2012-11-23T09:14:02.673 回答