使用@OrderColumn和派生实体在JPA中加入Subclass策略

时间:2015-02-10 17:12:45

标签: java hibernate jpa

我尝试使用已连接的子类策略实现继承,同时跟踪组合实体列表的顺序。

我有一个SHOP表,带有ID和一些元数据。

SHOP必须维护几种类型实体的有序列表,这些实体具有一些共同的元数据。

这就是我目前在实体和映射方面所拥有的:

@Entity
public class Shop extends PersistedEntity {

    // Persistend entity is a common class that declares the @Id column as:
    // @Id
    // @GeneratedValue(strategy = GenerationType.AUTO)
    // public int getId() {
    //  return this.id;
    // }

    // ... some generic fields

    private List<ShopAssets> shopAssets = new ArrayList<ShopAssets>();

    @ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
    @JoinTable(name = "ShopAssets", joinColumns = { @JoinColumn(name = "shop_id") }, inverseJoinColumns = { @JoinColumn(name = "id") })
    @OrderColumn(name="position")
    public List<ShopAssets> getShopAssets() {
        return shopAssets;
    }
}


@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "assetType")
public class ShopAsset extends PersistedEntity {

    // Again, the id integer column is inherited from PersistedEntity

    private Shop shop;
    private int position;
    private ShopFieldAsset keyAsset;

    @ManyToOne
    @JoinColumn(name = "shop_id")
    public Shop getShop() {
        return shop;
    }

    public int getPosition() {
        return position;
    }

    @ManyToOne
    @JoinColumn(name = "keyAsset_id")
    public ShopFieldAsset getKeyAsset() {
        return keyAsset;
    }

    // ... setters not included
}


@Entity
@DiscriminatorValue("field")
@PrimaryKeyJoinColumn(name = "id")
public class ShopFieldAsset extends ShopAsset {

    // ... bunch of standard string properties

}

@Entity
@DiscriminatorValue("common")
@PrimaryKeyJoinColumn(name = "id")
public class ShopCommonAsset extends ShopAsset {

    // ... bunch of standard string properties

}

@Entity
@DiscriminatorValue("expired")
@PrimaryKeyJoinColumn(name = "id")
public class ShopExpiredAsset extends ShopAsset {

    // ... bunch of standard string properties

}

数据库表如下(粗略地):

Shop: id(PK). name, location
ShopAsset: id(PK), shop_id, assetType, position, keyAsset_id(FK on ShopFieldAsset[id])
ShopFieldAsset: id(PK and also FK to ShopAsset[id]), name, type, other standard columns);
ShopCommonAsset: id(PK and also FK to ShopAsset[id]), name, type, other standard columns);
ShopExpiredAsset: id(PK and also FK to ShopAsset[id]), name, type, other standard columns);

我在测试中试图做的就是创建一个商店并用一系列资产来维护它,并保持它们被添加到商店的顺序。

我得到的是:

org.hibernate.MappingException: Foreign key (FK_ep3g3p25oddon8apvq8kgji6w:ShopFieldAsset [id])) must have same number of columns as the referenced primary key (ShopAsset [shop_id,position])

我只是不知道主键定义来自哪里......

我意识到衍生实体可能会妨碍(任何ShopAsset在ShopFieldAsset子类上都有一个外键的事实......)但是我对如何定义映射感到困惑。

好像这还不够,如果/当我开始工作时,是否有一种聪明的方法可以在商店购买吸气剂来检索特定类型的资产集合,例如: getShopCommonAssets()?我简单地研究过使用@Where,但很明显我把它留在了一边,直到我得到了基础知识!

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

令人惊讶的是晚安睡得好。

我解决了大部分问题:

  1. 通过删除父Shop实体上的@JoinTable注释。看起来这是在尝试添加ShopAsset时混淆插入语句的原因。

  2. 通过更改子类来实现:

    @PrimaryKeyJoinColumn(name =&#34; id&#34;,referencedColumnName =&#34; id&#34;)

  3. 而不仅仅是

    @PrimaryKeyJoinColumn(name = "id")
    

    现在看起来很高兴,甚至@OrderColumn也没问题。

    我找到了一个答案来帮助我解决问题的最后部分:

    How to map collection of each subclass from same hierarchy onto one owning class?

    但是当我试着这样做时:

    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, mappedBy = "shop", targetEntity = TornadoLabel.class)
    public List<ShopCommonAssets> getShopCommonAssets() {
        return shopCommonAssets;
    }
    

    我正在

    org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.shopping.ShopCommonAsset.shop in com.shopping.Shop.shopCommonAssets
    

    我猜是因为我的店铺&#39;属性在父类上,与我链接到的答案中的示例不同。