0

我正在使用 Play 框架编写一个应用程序,该框架使用 JPA 注释和 Hibernate 作为包含的 Ebean ORM 持久层的一部分。我在找出与外键相关的 JPA 注释时遇到了一些麻烦。在我的 MySQL 数据库中,有一个名为 Locations 的主表,用于存储地址(街道、城市、州、邮编等)。数据库中的许多其他表以一对一或多对多的关系使用此表。问题是,当我尝试将多个字段映射到 Locations 中的 id 字段时出现错误。

例如,Docks 和 LineItems 是两个包含对 Location 的引用的模型。每个 Dock 都有一个 Location,每个 LineItem 有两个 Location:一个起点和一个终点。

所以,在 Dock 中,我有代码:

@OneToOne(optional=false)
@JoinColumn(name="loc_id")
public Location location;

在 LineItem 中,我有:

@OneToOne(optional=false)
@JoinColumn(name="origin")
public Location origin;

@OneToOne(optional=false)
@JoinColumn(name="destination")
public Location destination;

但我无法将它们全部映射到 Locations 中的 id 字段,因为 JPA 不允许我这样做:

@Id
@GeneratedValue
@OneToOne(mappedBy="location", fetch=FetchType.EAGER)
@OneToOne(mappedBy="origin", fetch=FetchType.EAGER)
@OneToOne(mappedBy="destination", fetch=FetchType.EAGER)
@Column(name="loc_id")
public Long id;

我有一种感觉,我只是走错了路。有没有更简单的方法在 JPA 中使用外键约束?我真的不想使用解决方法,比如在我的表中创建一堆额外的列,因为 Locations 确实被引用了很多。任何让我直截了当的建议将不胜感激。

4

1 回答 1

0

您显示的位置配置没有任何意义。如果可以完全按照您的意图进行解释,这对 JPA 意味着什么:

  1. Location 有一个 Long “id” 属性,它是一个生成的值,并映射到 loc_id 列。
  2. “id”属性是一个 Dock,是 Dock 和 Location 之间一对一、双向关系的非拥有端。
  3. 它也是一个 LineItem,它是来自 LineItem 的一对一双向关系的非拥有端,既是起点是终点。

显然这没有任何意义,对吧?如果您要@OneToOne在 Location 中包含所有这些注释,则每个注释都需要位于其自己的字段中:一个 Dock 和两个 LineItem,以及您提到的与 Location 的所有其他关系的更多注释。这显然是不可取的,因为 Location 就是这样,其他东西引用它并不重要。所以你真正想要的是一堆与位置的单向关系。由于您已经将 Location 映射为非拥有端(通过“mappedBy”参数),您所要做的就是@OneToOne从 Location 中删除 s。您所需要的只是,例如:

@OneToOne
@JoinColumn(name="origin")
public Location origin;

也就是说,“origin”属性是其主键存储在该实体映射到的表的“origin”字段中的位置。

在这方面,我希望所有这些都不是真正的一对一关系。至少 LineItem 是一对多的。我无法想象两个订单项永远不会有相同的起点或终点。

顺便说一句,optional=false它是默认值,但如果您认为它会阻止该字段为空,那么它不会。可选参数只是告诉 JPA 在外键引用的行丢失时是否抛出异常。

这是一种高级别的概述。如果您不了解其中的某些内容,请提出更多问题。Hibernate Annotations 指南应该可以帮助您理解其中的大部分内容,并且让 hibernate 为您生成数据库模式也非常有帮助,这样您就可以查看它是否理解您所说的表结构。

于 2013-01-01T05:35:47.720 回答