hibernate @DiscriminatorValue不适用于关联

时间:2009-11-09 17:23:22

标签: hibernate annotations associations hibernate-annotations

我有以下继承层次结构。

@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=?

2 个答案:

答案 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,因此作为集合加载查询的一部分被检索。这里的问题是 - 它是如何插入的?有两种可能的情况:

  1. BananaApple的子类。在这种情况下,一切都是正确的,它应该作为apples集合的一部分返回。
  2. 您已手动插入上述数据以进行测试。从Hibernate的角度来看,这些数据是非法的 - 它可能会被Hibernate本身插入 NEVER ;这反过来导致你所看到的行为。您需要删除Banana行或删除其entity_id(从而将其从apples集合中移除)。
  3. 一般来说,在同一个表中混合对象层次结构和集合元素并不是一个好主意。考虑将层次结构重新映射为“table-per-subclass”或使用apples映射@JoinTable集合 - 请注意,在后一种情况下它将变为单向。