使用Hibernate,我可以在同一个表中混合table-per-subclass和<map>吗?</map>

时间:2009-08-06 19:41:13

标签: java hibernate orm

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

不同的促销代码可能有不同类型的“好处”,这意味着我们给予客户的是什么。 例如:促销代码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中的每子类表支持适用于子类表中​​的单个行映射到父表中的单个行的实例 - 并且映射<map>应该引用到第二个包含键/值的表。

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

1 个答案:

答案 0 :(得分:1)

每子类表策略意味着您将为层次结构中的每个类(包括抽象类,如果有)创建一个表,并且它们都将具有共享主键。在您的情况下,这意味着您将为BenefitFreeMinutesBenefitPriceDiscountBenefit类提供单独的表格。您的表名有点令人困惑,表结构与table-per-subclass有些不一致。

假设map_id是共享主键,BenefitDetails_PriceDiscount表必须如此定义它。 plan_id属于不同的('映射) table that will hold a map between PriceDiscountBenefit ,计划'和小数值。换句话说:

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)
);