【问题标题】:How to map many-to-many association to a class mapped to two different tables?如何将多对多关联映射到映射到两个不同表的类?
【发布时间】:2010-12-12 08:07:10
【问题描述】:

我有一张 Voucher - POJO 映射到两个表。第一个映射分配实体名称“voucherA”并将 POJO 映射到 TableA。第二个映射使用“voucherB”作为实体名称,并将 POJO 映射到 TableB。

现在我还有一个客户 POJO 映射到 TableC。此 POJO 引用列表中的凭证。

<list name="vouchers" table="TableC_vouchers">
  <key column="pid"/>
  <list-index column="position" base="0"/>

  <!-- how to do that right -->
  <many-to-many column="voucher_id" entity-name="voucherB"/>
</list>

我如何正确地映射从客户到凭证的多对多关联列表,以便如果客户 POJO 被持久化,则如果 Voucher 实体不存在,则将其持久化到 TableB,而不是 TableA?这可以做到吗?如果不是,那么将客户使用的凭证保存到 tableB 的解决方法是什么? (TableA 只包含可用的 Vouchers,不包含已使用的 Vouchers)

【问题讨论】:

  • 只是为了澄清一下,您是否对每种凭证都使用一张表格?将两种类型的凭证存储在一个表中会不会不可接受?
  • 第二个表应该只包含那些已经使用的凭证。同样在我的情况下,不同用户可以多次使用一张优惠券。在我的问题中,TableA 可以理解为“仍可使用的优惠券”和 TableB“已使用的优惠券”。也可能发生 TableA 中的凭证被删除的情况。我不知道如何创建多对多关联。
  • 我明白了。如果您在表中为每张凭证存储一个标志,如果使用凭证则为 true,否则为 false,这将是不可接受的。我认为这样你仍然可以随意删除未使用的,但你可以将所有凭证放在同一个表中,这使得多对多变得微不足道。
  • 我的偏好是两张表解决方案,但如果这不可能或实施起来太复杂,我会选择一张表解决方案
  • 感谢您的澄清。我认为这是最简单的路线。您可以在下面找到我的“官方”答案。

标签: java hibernate hibernate-mapping


【解决方案1】:

您的核心模型似乎错误。您的Voucher 实体可能具有许多属性 - 在Customer 使用后,它们是否都发生了变化?我不信。然而,您将它们复制到 A 和 B 表中,这意味着您的架构未标准化。

“可用”优惠券和“已使用”优惠券不是(或不应该)同一个实体。相反,我建议您为UsedVoucher 创建一个新实体,该实体将链接到Voucher 作为多对一和Customer 作为多对一并且仅包含Voucher 的“更改”属性(如果有)。所以,

Voucher(id, other attributes) // doesn't change from what you have now
Customer (id, other attributes) // doesn't change except for many-to-many; see below
UsedVoucher(id,
 voucher, // what Voucher was used by that customer
 customer, // what Customer has used that voucher
 changed voucher attributes, // if any
 additional attributes // if needed, such as date/time when voucher was used
)

如果您需要它作为可维护的财产,您在Customer 上的“多对多”将变为“一对多”(此客户使用的优惠券集合);否则很容易通过查询来检索。

但是,在这种情况下,您无法从Vouchers 表中物理删除(除非从未使用过相关凭证)。您必须改为执行逻辑删除。

【讨论】:

  • 我同意你的回答。顺便说一句,有时选择具有非规范化模式是合法的。使用 Hibernate,代码中的设计会严重影响模式。如果您使用 table-per-subclass 继承,您的问题可能会更容易做某事。做出这种选择通常意味着您将复制数据。因此,我不会说模型是“错误的”。
  • Lyudmil - 有不同种类的非规范化,有些比其他更容易接受。不过,在这种情况下,根据我对 OP 想要什么的理解(公平地说,他还不是很清楚),我绝对会建议不要将所有东西捆绑在一张桌子上。您最终会得到“基本”凭证和多个“已声明”凭证,从而导致无法拥有任何有意义的 FK/业务密钥约束。此外,我说“似乎错了”:-) - 再次,根据我的理解。
【解决方案2】:

我的建议是将所有代金券存储在同一张表中。要区分已使用和未使用的,您可以使用布尔标志或鉴别器值(如果您在 Java 代码中使用继承)。

即使您拥有现有数据,迁移似乎也不会非常困难。一旦所有凭证都在同一个表中,它们与客户的关系就变成了直接的多对多。

我认为维护两个表会很困难。本质上,您仍在存储是否使用凭证,但您并没有明确地这样做。我确信可能有一种解决方法,但我认为我上面概述的要简单得多。根据我的经验,这是我每次遇到类似问题时都会选择的路线。

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2021-10-30
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多