2013-07-24 20 views
4

JPA管理依赖关系的方式让我感到非常紧张。如果我有一个实体父母,并且我想要另一个实体孩子,当父母被删除时清理,那么似乎我必须有一个硬编码的依赖关系。这对我想如何布置我的软件包造成严重破坏。JPA似乎强制软件包之间的循环依赖关系

例如,考虑我有一个名为User的实体。后来,我想添加Facebook功能。所以我想为用户添加Facebook令牌和ID。我创建了一个Facebook包来包含我所有的facebook特定插件代码。我的FacebookInfo实体包含用户实体引用。但现在我有一个问题。我想在删除用户时删除FacebookInfo记录。这迫使我添加一个FacebookInfo引用到用户创建一个双向关系。而BAM,现在我在“用户”和“脸谱”包之间有一个循环。除了支持级联删除以外,我不需要在用户中使用FacebookInfo。理想情况下,我希望FacebookInfo实体类指定它想要在用户时被删除。然后所有的依赖关系都是单向的。

当使用JPA时,大多数人是否依赖循环依赖关系来打包?或者有没有体面的方法来避免这种情况?如果有一种特定于hibernate的方式来处理这个问题(不使用XML),我也可以这样做。谢谢。

+0

使用双向关系只是让JPA知道用户有Facebook实体需要删除。如果你不想引用,那么你需要一些其他方式来告诉它有需要删除的Facebook实体。事件是一种方式,另一种应用知识。即您的removeUser方法可以查询Facebook相关实体并删除它们,以及为用户调用remove。或者使用JPQL批量删除。或者使用preRemove事件,将依赖关系放入不同的类/包中。使用JPA 2.1,实体听众可以使用CDI – Chris

+0

当然,我可以推出自己的产品,这可能是我会做的。看起来很奇怪,JPA认为适合在SQL中反转ON DELETE依赖关系。他们把它放在依赖表上是有原因的。有时我希望JPA没有尽力抽象出对象 - 关系阻抗不匹配。 –

回答

2

大部分人都使用JPA时踢在包循环依赖

以我的经验[?]:使用JPA时不但。这是使许多大型代码库如此可怕的许多事情之一。

有没有体面的方法来避免这种情况?

基本的想法是使用接口,我看到两个选项来应用它。一个使用JPA,但我不能承诺它的工作原理。另一个或多或少独立于JPA。

的JPA方式

相反引用回FacebookInfo参考回接口ExtraUserInfo的,然后让FacebookInfo实现该接口(或抽象类)。 ExtraUserInfo将与用户在同一个包中,所以所有的循环都消失了。我不确定这样的基于接口的映射是否可行,但是如果它起作用,它应该具有预期的效果。

JPA独立

您可以创建一种机制,之前删除(或任何其他相关的行动)一Listener得到通知。此外,Listener接口和整个机制将驻留在User程序包中(或更有可能在User程序包所依赖的程序包中),而Listener的实际实现将驻留在UserInfo程序包中。根据您的架构,可能会有各种地方来建立这样的通知机制。可能位于持久层中的存储库中。实际上我认为JPA本身支持这种通知机制,所以这可能会变成另一种JPA基础解决方案。

+0

我不知道如何将实体作为接口引用。真的,用户甚至不需要知道人们“扩展”它。 JPA基本上强制表格在用新关系进行扩展时被修改。你的第二个建议可能是我最终会做的。我可以在用户中自动装入这些元素,以便FacebookInfoDeleteListener可以实现UserDeleteListener接口。谢谢!仍然不明白为什么JPA不允许在依赖实体上使用ON DELETE规范。奇怪的。 –