成为房地产所有者的意义何在?CASCADE如何在JPA中与双方合作?

时间:2018-08-30 05:36:39

标签: java hibernate eclipselink persistence jpa-2.1

我有两个桌子。交易和错误。事务和错误之间存在一对多关系。这是双向关系,并且Errors是拥有方,因为在Errors类中指定了@JoinColumn。我想了解“ OWN”关系的确切含义。现在说,

  • 已处理(交易中的列)设置为N
  • 有效(错误列)设置为1

方案1: 现在,假设我们执行以下代码。

transactions.setProcessed("Y");
errors.setActive(0);
transactions.setErrors(errors);
entityManager.merge(transactions);

我了解在TRANSACTIONS中PROCESSED字段将被设置为“ Y”,但是如果事务不是该关系的所有者,则在ERRORS中的ACTIVE字段也将被设置为0吗?

方案2: 另一方面,如果执行以下命令:

errors.setActive(0);
transactions.setProcessed("Y");
errors.setTransactions(transactions);
entityManager.merge(errors);

我知道ERRORS中的ACTIVE字段将设置为0,但鉴于ERRORS是关系的所有者,则TRANSACTIONS中的PROCESSED字段也将设置为“ Y”吗?

JPA级联类型如何与此类方案联系起来?

2 个答案:

答案 0 :(得分:1)

当我们说错误是拥有方时,这意味着关系的外键位于错误表中(您通过@JoinColumn执行此操作)。因此,关系的拥有方是另一个实体的参考列将出现在其中的一方。 您可以通过在Transactions实体中指定@OneToMany来定义关系的反面。

现在是您有关交易更新和错误的问题的第二部分。在我看来,您可以通过应用适当的级联模式(持久性,删除等)来更新与交易相关的列表,这意味着您可以在交易实体@OneToMany(cascade=CASCADETYPE.MERGE)中进行指定,同时指定反向关系。这样,如果每当您要更新事务行时,也可以更新相应的错误行。

但是,我认为以另一种方式进行级联不是一个好习惯,即,如果您更新子实体,那么父实体也应该得到更新,因为这可能导致许多数据不一致

答案 1 :(得分:1)

在非双向关系中,您定义一个映射。当您对该映射进行更改时,很明显会发生什么-外键将得到更新。因为只有一个映射,所以不会发生冲突(许多JPA提供程序如果检测到一个字段有多个可写映射,就会抛出错误。)

具有双向关系,这种控制不太明显。在您的transaction-Error双向关系中,假定它是一个OneToOne双向映射,并且Transaction1设置为指向Error1,反之亦然。假设您的应用程序确定Transaction1应该改为指向Error2,然后更改引用。如果没有更正Error1对Transaction1的引用以反映这种情况,则JPA在确定要放入外键中的值时存在问题。这就是所有权发挥作用的地方。拥有方被认为是可写映射,对其进行更改以控制外键字段。在OneToMany中,拥有方通常是ManyToOne的后向引用,因为它更自然,因为外键始终位于持有ManyToOne的表中。如果您进行了更改以将错误添加到事务中,但不更改该错误以也引用该事务,则您的对象模型将与数据库中的内容不同步-错误中的外键不会更改,但是事务对象将在其列表中显示错误,直到从数据库刷新或重新加载该对象为止。

级联与所有权无关。这仅表示操作(持久,合并,删除,刷新)适用于该关系引用的实体。如果使用cascade.all调用em.refresh(transaction),则将从数据库中刷新事务和所有引用的错误。然后,具有错误的级联设置为ALL或REFRESH的任何关系也将刷新,依此类推。如果将JPA放在引用的事务实例上,JPA应该检测到它已经刷新了,但是为什么要冒险。通常,级联选项应仅放置在需要避免不必要后果的映射上。如果不确定是否需要它,请在确定之前将其保留。当有人去到各处进行级联刷新时,诸如延迟获取和其他优化之类的事情可能会导致各种奇怪且难以发现的错误。

在您的示例中,您可以在应用程序将要传递的根实体上进行级联合并。然后,只需一次合并调用即可轻松获取对该图所做的任何更改,而不必在每个单独的叶子上调用合并。模型的构建和序列化方式会影响合并,因此通常将级联选项仅放在root-> Leaf关系上,以避免出现root-> leaf-> root'where root!= root'的问题。如果双方都有级联合并,则root'的状态可能会覆盖root中的更改。