2 回答
TA贡献1943条经验 获得超7个赞
当我们说 Errors 是拥有方时,这意味着关系的外键位于 Errors 表中(您正在通过@JoinColumn
)。因此,关系的拥有方是另一个实体的引用列将出现的一方。您可以通过@OneToMany
在 Transactions 实体中指定来定义关系的反面。
现在是关于交易和错误更新的问题的第二部分。在我看来,您可以通过应用适当的级联模式(持久、删除等)来更新与事务关联的列表,这意味着您可以在@OneToMany(cascade=CASCADETYPE.MERGE)
指定反向关系的同时在事务实体中指定。这样,如果每当您更新一个事务行时,也可以更新相应的错误行。
但是,我认为以其他方式级联不是一个好习惯,即如果您更新子实体,则父实体也应该更新,因为它可能会导致许多数据不一致
TA贡献1796条经验 获得超10个赞
在非双向关系中,您定义一个映射。当您对该映射进行更改时,很明显会发生什么 - 外键将被更新。因为只有一个映射,所以不会有冲突(许多 JPA 提供程序如果检测到您有多个可写的字段映射,就会抛出错误)。
对于双向关系,这种控制不太明显。在您的 transaction-Error 双向关系中,假设它是一个 OneToOne 双向映射,并且 Transaction1 设置为指向 Error1,反之亦然。假设您的应用程序确定 Transaction1 应该指向 Error2,并更改引用。如果 Error1 对 Transaction1 的引用没有更正以反映这种情况,那么 JPA 在确定将什么值放入外键时就会出现问题。这就是所有权发挥作用的地方。拥有方被认为是可写的映射,对它的更改控制外键字段。在 OneToMany 中,拥有方通常是 ManyToOne 反向引用,因为它更自然,因为外键无论如何都在持有 ManyToOne 的表中。
级联与所有权无关。它只是意味着操作(持久化、合并、删除、刷新)适用于关系引用的实体。如果使用cascade.all 调用em.refresh(transaction),事务和所有引用的错误将从数据库中刷新。任何具有 ALL 或 REFRESH 级联设置的 Error 关系也将被刷新,依此类推。如果你把它放在后面的引用上,JPA 应该检测到它已经刷新了引用的 Transaction 实例,但为什么要冒险呢。通常,级联选项应仅放置在需要避免意外后果的映射上。如果您不确定是否需要它,请在确定之前将其关闭。
在您的示例中,您可能会在应用程序将传递的根实体上进行级联合并。对该图所做的任何更改都可以通过单个合并调用轻松获取,而无需在每个单独的叶子上调用合并。您的模型的构建和序列化方式会影响合并,因此通常级联选项仅放在根-> 叶关系上,以避免出现根-> 叶-> root' where root != root' 的问题。如果双方都有级联合并,则 root' 的状态可能会覆盖您在 root 中的更改。
添加回答
举报