【问题标题】:With Hibernate, can I mix table-per-subclass and a <map> within the same table?使用 Hibernate,我可以在同一个表中混合 table-per-subclass 和 <map> 吗?
【发布时间】:2009-08-06 19:41:12
【问题描述】:

我正在尝试为“促销”映射一个对象模型;即,客户在注册期间输入促销代码。

不同的促销代码可能有不同类型的“好处”,即我们为客户提供的内容。 例如:促销代码 XYZ123 将在客户的帐户中为客户提供免费分钟,而不同的促销代码将为用户在注册时可以选择的各种订阅计划提供各种折扣。

在我的领域模型中,我将不同类型的好处建模为具有共同属性的抽象超类的子类。我选择将不同类型建模为子类,因为某些类型的好处需要不同的属性。

public abstract class Benefit {
    //getters/setters for common attributes
}

public class FreeMinutesBenefit extends Benefit {
    public int getFreeMinutes() {...}
    public void setFreeMinutes(int minutes} {...}
}

public class PriceDiscountBenefit extends Benefit {
    public Map<Plan, BigDecimal> getDiscountMap() {...}
    public void setDiscountMap(Map<Plan, BigDecimal> map) {...}
}

粗略的 SQL 架构:

-- Parent table, maps promotion to benefits
create table Promo_Benefit (
    map_id integer auto-generated PRIMARY KEY,
    promo_id integer references PROMOTION(promo_id),
    type_id integer references BENEFIT_TYPES(type_id)
);

create table BenefitDetails_FreeMinutes (
    map_id integer PRIMARY KEY,
    minutes integer not null,
    FOREIGN KEY (map_id) references Promo_Benefit(map_id)
);

create table BenefitDetails_PriceDiscount (
    map_id integer references Promo_Benefit(map_id),
    plan_id integer references Plans(plan_id),
    reduced_price numeric not null,
    PRIMARY KEY (map_id, plan_id)
    FOREIGN KEY (map_id) references Promo_Benefit(map_id)
);

我能够在我的 Hibernate 映射文件中成功映射每个子类的基本属性,但我无法弄清楚如何映射关联 在 PriceDiscountBenefit 子类和 Plan 类之间。

我想这是因为子类表 (BenefitDetails_PriceDiscount) 的主键不仅仅是 map_id 列 - 换句话说,这个子类表中的多行将形成一个单一的 PriceDiscountBenefit 实体。从我所见,Hibernate 中的每个子类表支持似乎是用于子类表中​​的单行映射到父表中的单行的实例 - 并且映射 &lt;map&gt; 应该指第二个包含键/值的表。

我映射这完全错误吗?我不知道我是否遇到了麻烦,因为我正在扼杀每个子类的表模式。

【问题讨论】:

  • Promo_Benefit 表来看,你有一个Promotion 类,它与Benefit 是一对多的关系。这是真的吗?

标签: java hibernate orm


【解决方案1】:

每个子类的表策略意味着您将为层次结构中的每个类(包括抽象类,如果有的话)都有一个表,并且它们都将具有共享的主键。在您的情况下,这意味着您将为 BenefitFreeMinutesBenefitPriceDiscountBenefit 类中的每一个都有一个单独的表。您的表名有点混乱,表结构与每个子类的表有些不一致。

假设map_id是共享主键,BenefitDetails_PriceDiscount表必须这样定义。 plan_id 属于不同的 ('mapping) table that will hold a map betweenPriceDiscountBenefit,Plan` 和十进制值。换句话说:

create table BenefitDetails_PriceDiscount (
        map_id integer PRIMARY KEY,
        ... /* any other attributes, perhaps? */
        FOREIGN KEY (map_id) references Promo_Benefit(map_id)
);

create table BenefitDetails_PriceDiscount_Map (
        map_id integer references Promo_Benefit(map_id),
        plan_id integer references Plans(plan_id),
        reduced_price numeric not null,
        PRIMARY KEY (map_id, plan_id)
        FOREIGN KEY (map_id) references Promo_Benefit(map_id)
);

【讨论】:

  • 谢谢。这可行,但感觉很奇怪 - 因为我的 BenefitDetails_PriceDiscount 只有一列(我不需要此表中的其他属性),即 FK。似乎...肮脏,从数据库设计的角度来看,好像我这样做只是为了支持 Hibernate
  • 从数据库的角度来看,这肯定有点奇怪,但这是唯一的方法。如果您根本没有层次结构(只有一个带有 id 和地图的实体),您仍然有两个单独的表 - 第一个只有 PK,第二个用于地图。如果您确定在 PriceDiscountBenefit 上永远不会有任何其他属性,您可以尝试使用 table-per-hierarchy 但最终会得到一些 NULL 列,具体取决于实体。
猜你喜欢
  • 2012-04-28
  • 1970-01-01
  • 2011-01-02
  • 2023-03-12
  • 2011-02-08
  • 1970-01-01
  • 2011-11-14
  • 2023-04-07
  • 2011-05-28
相关资源
最近更新 更多