我有以下继承层次结构。
@Entity
@Table(FRUIT)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColum(name="FRUIT_TYPE",discriminatorType=STRING)
public class Fruit {
..
@Id
private FruitId id;
...
}
@DiscriminatorValue("APPLE")
public class Apple extends Fruit {
...
@ManyToOne
private FruitBowl bowl; //this association is only present in the subclass
...
}
class FruitBowl .. {
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "bowl")
@IndexColumn(name="POSITION",base = 1)
List<Apple> apples;
...
当我执行session.load(Apple.class,...)
时,会向选择查询添加FRUIT_TYPE = 'APPLE'
。但是,如果我在FruitBowl(与Apple有1:m的关系)上进行选择,则Apple上的选择查询不包含FRUIT_TYPE = 'APPLE'
。为什么会这样?我该如何纠正这个问题?
查询 - FruitBowl的查询
select fruitbowl0_.BOWL_ID as BOWL1_1_0_ from FRUITBOWL fruitbowl0_ where fruitbowl0_.BOWL_ID=?
- 查询Fruit以检索苹果(带有fruit_type ='A'的记录) - 但它不包括该条件
select apples0_.ENTITY_ID as ENTITY3_1_, apples0_.POS as POS1_, apples0_.POS as POS0_0_, apples0_.ENTITY_ID as ENTITY3_0_0_, apples0_.COLOR as COLOR0_0_ from FRUIT apples0_ where apples0_.ENTITY_ID=?
答案 0 :(得分:4)
您可以将@DiscriminatorOptions(force=true)
添加到“Fruit”类中,这将强制hibernate在查询此关系时使用descriminator。
这似乎是默认情况下你会期望的东西,但也许有一些性能原因导致它不是这样。
答案 1 :(得分:0)
(根据问题/评论中发布的映射/ SQL查询/样本数据编辑)。
您的映射指定FruitBowl
包含Apple
的集合。因此,Hibernate不会为该集合的加载器查询添加鉴别器值条件,因为它事先知道只能返回Apple
个实例。
您发布的SQL查询就是这样做的 - 按ID加载FruitBowl
,然后为该apples
实例加载FruitBowl
集合。问题在于您发布的数据:
fruit_type entity_id pos color A 1 1 white B 1 2 blue
另一个Fruit
的实例带有鉴别值B
- Banana
? :-) - 具有相同的entity_id
,因此作为集合加载查询的一部分被检索。这里的问题是 - 它是如何插入的?有两种可能的情况:
Banana
是Apple
的子类。在这种情况下,一切都是正确的,它应该作为apples
集合的一部分返回。Banana
行或删除其entity_id
(从而将其从apples
集合中移除)。一般来说,在同一个表中混合对象层次结构和集合元素并不是一个好主意。考虑将层次结构重新映射为“table-per-subclass”或使用apples
映射@JoinTable
集合 - 请注意,在后一种情况下它将变为单向。