2

我有以下继承层次结构。

@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;
...

当我执行 asession.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_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=?
4

2 回答 2

4

您可以添加@DiscriminatorOptions(force=true)到“水果”类中,这将强制休眠在查询此关系时使用描述符。

这似乎是您默认情况下所期望的,但也许有一些性能原因导致它不是这样。

于 2012-10-17T03:54:43.180 回答
0

(根据问题/评论中发布的映射/SQL 查询/示例数据进行编辑)。

您的映射指定FruitBowl包含Apples 的集合。因此,Hibernate 不会将鉴别器值条件添加到该集合的加载器查询,因为它事先知道只能Apple返回实例。

您发布的 SQL 查询正是这样做的——FruitBowl按 id 加载,然后apples为该FruitBowl实例加载集合。问题在于您发布的数据:

fruit_type entity_id pos 颜色
     A 1 1 白色
     B 1 2 蓝色

Fruit还有另一个带有鉴别器值的实例B- Banana?:-) - 具有相同的entity_id内容,因此作为集合加载查询的一部分进行检索。这里的问题是 - 它是如何插入的?有两种可能的情况:

  1. Banana是 的子类Apple。在这种情况下,一切都是正确的,它应该作为apples集合的一部分返回。
  2. 您已手动插入上述数据以进行测试。从 Hibernate 的角度来看,这些数据是非法的——它永远不会被 Hibernate 本身插入;这反过来又会导致您看到的行为。您需要摆脱Banana行或删除其entity_id(从而将其从apples集合中删除)。

一般来说,在同一个表中混合对象层次结构和集合元素并不是一个好主意。考虑将层次结构重新映射为“每个子类的表”或apples使用映射集合@JoinTable- 请注意,在后一种情况下它将变成单向的。

于 2009-11-09T17:53:40.640 回答