2

使用的休眠版本:

  <artifactId>hibernate-annotations</artifactId>
  <version>3.5.5-Final</version>

  <artifactId>hibernate-core</artifactId>
  <version>3.5.5-Final</version>

  <artifactId>hibernate-commons-annotations</artifactId>
  <version>3.2.0.Final</version>

  <artifactId>hibernate-jpa-2.0-api</artifactId>
  <version>1.0.0.Final</version>

假设有两只猫(猫和它的伴侣有相同的小猫)猫/猫的伴侣与它的小猫有关系,小猫的名字作为连接列(连接列上的 OneToMany 关系,获取类型为“eager”)

假设我想得到小猫名字为“大”的猫,为此,我可以用不同的方式编写 hql。

I.

hql.append("from Cat as cat ")
hql.append("where cat.kitten.name = 'big' ");

II.

hql.append("from Cat as cat inner join cat.kitten as kitten ")
hql.append("where kitten.name = 'big' ");

前面提到的 hql 在 cat 和它的小猫之间生成了一个内部连接,并且按预期工作。

但是,如果我想查询 kitten 中的一个属性,其中 cat 没有加入 kitten (比如 location ),我可以编写 hql 如下:

III.

hql.append("from Cat as cat ")
hql.append("where cat.kitten.location = 'Chicago' ");

IV.

hql.append("from Cat as cat inner join cat.kitten as kitten ")
hql.append("where kitten.location = 'Chicago' ");

问题 1) III 和 IV 也按预期工作,但是,III 正在 cat 和它的小猫之间生成笛卡尔/交叉连接,而没有 hql 中提到的显式连接,而 IV 不是。这是为什么?

说,我想在 hql 中加入两个“不同”的对象 cat 和 mate (没有任何关联),它正在生成交叉连接。

例如,如果我说,

V.

hql.append("select cat ")
hql.append("from Cat as cat, Mate mate ")
hql.append("where cat.location = mate.location and mate.location = 'Chicago' ");

它生成交叉连接。

但是,如果我说,

VI.

hql.append("from Cat as cat ")
hql.append("where cat.location in ( select mate.location from Mate mate where mate.location = 'Chicago' ");

问题 2)它不会生成交叉连接。但是,如果我必须使用两列怎么办。我需要使用两个 in 子句才能没有由 hql 生成的交叉连接。为什么一定要明确?或者如果可能的话,是否有休眠配置来避免交叉连接?

4

1 回答 1

0

在第一种形式(I、III、V)中,表之间的连接条件在映射中定义(可能在 a <one-to-many>、或子句中)<many-to.one>。在示例中,您似乎定义了一个正确的,而在 III 和 V 中,您没有正确执行。<one-to-one><many-to-many>

在示例 II、IV 和 VI 中,您明确定义了连接(或子选择)。如果 HQL 语句中有连接,Hibernate 总是在单个 SQL 语句中使用这个连接(如果连接是在映射中定义的,则不是这种情况 - Hibernate 通常更喜欢两个独立的选择(延迟加载仅在那时起作用)) . 这在以下情况下很有用.

如果我们要告诉你为什么 III 和 V 不能工作并产生笛卡尔积,那么你必须给我们表格的映射。

于 2012-06-14T07:34:59.677 回答