使用@OrderColumn 和派生实体在 JPA 中加入子类策略
Joined Subclass strategy in JPA with @OrderColumn and derived entities
我正在尝试使用联合子类策略实现继承,同时跟踪组合实体列表的顺序。
我有一个 SHOP table,有一个 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
}
数据库table如下(粗略):
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 子类上都有一个外键...),但我不知道应该如何定义映射。
好像这还不够,if/when 我让它工作了,有没有一种聪明的方法可以让 Shop 上的 getter 检索特定类型的资产集合,例如getShopCommonAssets() ?我简要地研究了使用@Where,但很明显我把它放在一边,直到我掌握了基础知识!
非常感谢任何帮助。
睡个好觉真是太神奇了。
我解决了大部分问题:
通过删除父 Shop 实体上的 @JoinTable 注释。看起来这就是在尝试添加 ShopAsset 时混淆插入语句的原因。
通过改变 subclasses 得到这个:
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
而不只是
@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
我猜这是因为我的 'shop' 属性 在父级 class 上,与我链接到的答案中的示例不同。
我正在尝试使用联合子类策略实现继承,同时跟踪组合实体列表的顺序。
我有一个 SHOP table,有一个 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
}
数据库table如下(粗略):
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 子类上都有一个外键...),但我不知道应该如何定义映射。
好像这还不够,if/when 我让它工作了,有没有一种聪明的方法可以让 Shop 上的 getter 检索特定类型的资产集合,例如getShopCommonAssets() ?我简要地研究了使用@Where,但很明显我把它放在一边,直到我掌握了基础知识!
非常感谢任何帮助。
睡个好觉真是太神奇了。
我解决了大部分问题:
通过删除父 Shop 实体上的 @JoinTable 注释。看起来这就是在尝试添加 ShopAsset 时混淆插入语句的原因。
通过改变 subclasses 得到这个:
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
而不只是
@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
我猜这是因为我的 'shop' 属性 在父级 class 上,与我链接到的答案中的示例不同。