【问题标题】:JPA @OneToMany with 1 - 1..* relationshipJPA @OneToMany 具有 1 - 1..* 关系
【发布时间】:2019-02-10 12:02:05
【问题描述】:

如何正确映射@OneToMany 关系在哪里创建实体,在@OneToMany 关系的@One 一侧,需要至少有一个来自@Many 一侧的实体,但@Many 一侧的实体也需要实体在@One 一侧存在吗?简单地说,这句话的噩梦,这就是我的场景:

这就是我想要的:

[ENTITY A] 1 <-----> (1..*)[ENTITY B]

目前我有这个:

[ENTITY A] 1 <-----> (0..*)[ENTITY B]

这很容易做到。

@OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
public Set<Agreement> agreements = new HashSet<>();

@ManyToOne
@JoinColumn(name = "CUSTOMER_ID", nullable=false)
private Customer customer;

所以问题是我的CUSTOMER 表没有与AGREEMENT 表对应的列,因此我不能执行创建Customer 的规则,只有在给出Agreement 时。目前我只能设置规则以在给出Customer 时创建Agreement,因为AGREEMENT 表有对应于CUSTOMER 表的列,这很容易通过nullable=false 条件完成。

【问题讨论】:

  • 我可能在这里误解了一些东西,但是没有外键就无法映射关系。您的 Join 列是如何成为 Customer 的主键?这根本没有意义。

标签: java hibernate jpa orm one-to-many


【解决方案1】:

这在很大程度上取决于您要强制执行的关系类型。如果协议可以独立于客户存在,则这意味着协议中的 customer_id 必须可以为空。

如果协议不能独立存在,则假定客户 ID 不可为空,在这种情况下,如果没有创建客户,就无法首先创建协议。这意味着您在客户和相应协议之间建立了更强的关联。

一旦我们定义了一段牢固的关系,我们就需要调查它的真实程度以及谁将拥有谁。通常,拥有关系的是多方,并且更新是通过多方进行的。这意味着您的 JoinColumn 需要在 MANY 上,并且映射的 by 需要在 ONE 一侧。

有趣的情况是,当 ONE 方实际拥有关系时,所有权是相反的,在这种情况下,多方的外键不能为 NULL,因为拥有 ONE 方无法知道 MANY 方是什么关键是。

【讨论】:

  • 我想创建没有协议的客户不能存在的关系,没有客户的协议也不能存在。目前,由于需要外键,如果没有客户,协议就无法存在,但由于客户中缺少任何外键,因此可以在没有协议的情况下创建客户。我正在考虑的解决方案,我不知道它是否正确或可能,具有@OneToMany 关系,其中客户的主键是 CUSTOMER_ID 的复合键和来自协议的外键,而协议的主键只是 AGREEMENT_ID 并且协议要求不为空外键。
  • @askstackoverflow 您无法以非编程方式实现此目的。只有一方拥有关系并控制对另一方的更新。正如另一个答案向您展示的那样,唯一可以实现这一点的方法是在休眠方面以编程方式进行。 ,或者通过在事务完成之前触发的数据库端实现一些东西。
  • 好的,谢谢,那我将坚持编程方式。
  • @askstackoverflow 。我不认为 N​​otNull 也是这样。如果您不能在没有协议的情况下拥有客户,那么您需要做的是不能首先插入协议,并且您应该拥有关系的拥有方成为客户。正确的做法是从客户到协议的单向一对多,这样您就可以创建一个强大的关联。由于单向关联的性质,它会创建一些额外的更新 SQL,但是关联的强度不会有问题。
【解决方案2】:

JPA 不提供验证这一点的方法,但 Hibernate Validator 提供:

@NotNull
@Size(min=1)
public Set<Agreement> agreements = new HashSet<>();

然后你必须通过验证器手动测试它:

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
validator.validate(customer)

【讨论】:

  • 谢谢,以编程方式防止这种情况的非常好的方法,当我想通过我的应用程序提供的服务向数据库添加一些东西时,这种方法很有效,但不幸的是我仍然可以在 h2 控制台中通过 SQL 创建客户。我正在尝试寻找解决方案,让我的数据库验证客户的插入。
  • 在 H2 或纯 SQL 中验证并不是那么容易,我相信它可能有点“hacky”所以不太干净。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多