如何处理指向通用接口的指针的 JPA 注释

Posted

技术标签:

【中文标题】如何处理指向通用接口的指针的 JPA 注释【英文标题】:How to handle JPA annotations for a pointer to a generic interface 【发布时间】:2010-05-11 05:19:16 【问题描述】:

我有一个泛型类,它也是一个映射超类,它有一个私有字段,其中包含指向另一个相同类型对象的指针:

@MappedSuperclass
public abstract class MyClass<T extends MyIfc<T>>
    implements MyIfc<T>
    

        @OneToOne()
        @JoinColumn(name = "previous", nullable = true)
        private T previous;

             ...
             

我的问题是 Eclipse 在 OneToOne 文件中显示错误“目标实体“T”之前不是实体。” MyIfc 的所有实现实际上都是实体。我还应该补充一点,从 MyClass 继承的每个具体实现都使用不同的 T 值(因为 T 本身就是),所以我不能使用“targetEntity”属性。

我想如果没有答案,那么我将不得不将此 JPA 注释移动到 MyClass 的所有具体子类中。 似乎 JPA/Hibernate 应该足够聪明,知道它会在运行时解决所有问题。让我想知道我是否应该以某种方式忽略此错误。

【问题讨论】:

【参考方案1】:

我的问题是 Eclipse 在 OneToOne 的文件中显示错误“目标实体“T” for previous is not an Entity。”

是的,即使 T 扩展了 Entity不知道有任何 JPA 提供者支持这一点(无论如何,这不是 JPA 规范的一部分)。如需更多反馈,请查看JPA Generic entities classes Mappedsuperclass are not possible!(关于 EclipseLink 的非常相似的帖子):

不,您将无法将实体设为通用。提供者将无法将关系映射到由泛型定义定义的特定类型,因为该类型是在使用代码创建实体时分配的,而不是在定义实体的地方。请记住,在指定泛型时,集合(在这种情况下)仅限于这些类型。 Provider 不可能在每个实体实例的基础上受到这种限制。在某些情况下,更改类型可能会导致为单个实体实例映射完全不同的表,这绝对不受支持。

【讨论】:

感谢您确认这是不可能的。实现继承永远不会按照您想要的方式工作的另一个原因。我将从抽象超类中删除对泛型类型的所有引用,并在所有具体实现中复制它们。我想知道使用 XML 映射文件而不是注释是否会更好? @HDave 我不认为这会改变任何事情,我希望您的 JPA 提供商在运行时抱怨。 即使没有,我认为编译类型的类型安全实体关系也值得高枕无忧。我今天不得不把这段 sn-p 的代码复制到 17 个具体的实体实现中,这真是太臭了! Oracle 可爱的把一切都搞砸了,您发布的主题的链接 (forums.sun.com/thread.jspa?threadID=5268944) 返回 404。无法在任何地方找到原始帖子(谷歌积分使用断开的链接返回这里和其他地方)。 oracle 内置搜索没有给出任何结果。你(或其他人)能给我一个新的链接吗?【参考方案2】:

由于 JDO 支持接口字段的持久性(这与您在此处所拥有的概念相似),并且由于 DataNucleus JPA 构建在 JDO 功能之上,因此它可能允许您持久化这样的字段(我有一个使用 JDO 的示例,它做了非常相似的事情,但是没有看到你的类的剩余部分和持久性代码,它不可能是确定的)。试一试,看看会发生什么。

显然这超出了 JPA 规范,因此如果您担心可移植性,那么请先考虑

【讨论】:

事实上,我也尝试过使用 JPA 并且也可以。所以不,这不是不可能的,正如其他回应所暗示的那样。它当然超出了 JPA 规范,但很有可能。你只需要使用 DataNucleus【参考方案3】:

您可以在您的字段中添加 @OneToOne(targetEntity=SuperClassOfT.class) 来完成这项工作。

查看How to implement polymorphic JPA entities with generic relations

【讨论】:

这个简单的技巧只有在从 SuperClassOfT 开始的层次结构使用单表策略映射时才有效。以链接中的示例为例,只要所有 Event 子类都映射到事件表中,您就可以告诉 Hibernate 使用 Event 作为目标,这意味着使用事件表来存储/查找所有目标实例。但是,例如,如果您想将 UserEvent 和 ApplicationEvent 映射到不同的表上,我认为您提出的解决方法不会奏效。 我猜join-table策略也可以,和single-table差不多,但我不确定。 @zakmck -- 这是一个很好的观点!我不确定当使用 table-per-class 策略时,hibernate 如何处理超类上的连接。也就是说,泛型信息仅与 java 类相关,您所说的其他限制在不使用泛型的情况下仍然存在,而是依赖于显式强制转换。

以上是关于如何处理指向通用接口的指针的 JPA 注释的主要内容,如果未能解决你的问题,请参考以下文章

进入智能指针,如何处理表示所有权?

单片机环形对接溢出如何处理

字符串类型数组的指针运算,C++如何处理这个?

JPA 2.0 如何处理死锁(Eclipselink JPA2.0 MySQL)

如何处理锁(JPA)?

如何处理和解析JPA持久性异常以向用户提供有意义的消息