我该如何解决这个Hibernate限制?

时间:2011-09-20 08:22:24

标签: java sql hibernate orm

我在层次结构中有3个实体,如下所示:

         MyInterface
              |
      -----------------
      |               |
   Entity1          Entity2

MyInterface未在Hibernate中映射(因为我使用implicit polymorphism strategy来映射此继承)

事实上,如果我发起像这样的查询:

"FROM MyInterface"

它工作正常(因为它检索Entity1的所有实例和Entity2的所有实例,将它们放在一起,并返回List<MyInterface>)。

如果我们查看Hibernate生成的SQL,它会启动2个独立的SQL查询来首先检索Entity1实例,另一个检索Entity2实例,但我对此很好。

当您尝试执行以下操作时会出现大问题:

"FROM MyInterface ORDER BY someField"

因为它将ORDER BY应用于第一个SQL查询,然后将相同的ORDER BY应用于第二个SQL查询,而不是将它们应用于整个查询(我知道这是因为我可以看到Hibernate启动的本机SQL查询。

这显然是Hibernate的一个小行星。

如何解决这个问题迫使Hibernate将ORDER BY应用于整个查询? (我不能在记忆中做到这一点,因为后来我也要添加分页)。

3 个答案:

答案 0 :(得分:1)

我想说问题是Hibernate必须创建这两个SQL查询,因为你必须从2个表中读取。

我不确定是否可以在一个查询中从2个表中读取并按两列(每个表中一个)排序(在没有特定于供应商的扩展名中),如果没有,Hibernate将不得不这样做无论如何都要在内存中订购。

应用分页时你可以做的是:读取你想要排序的id和值(不是整个实体),然后在内存中排序并读取页面中包含的所有id的整个实体。为了使分页保持一致,您可能必须存储该初始查询的结果(id +订单标准)。

答案 1 :(得分:1)

您的思维方式无法按原样映射到SQL。假设您Entity1包含字段field1Afield1B ...和Entity2字段field2Afield2B,...现在您想要要执行的以下查询:

SELECT Entity1.* FROM Entity1
UNION
SELECT Entity2.* FROM Entity2
ORDER BY CommonField

这在SQL世界中是不可能的,因为实体具有不同数量的字段和不同的字段类型。

因此,您需要考虑将公共字段提取到单独的表CommonEntity中,将您的界面转换为独立实体,并将其与一对一映射转换为Entity1&amp; Entity2(见Table per subclass)。然后SQL将如下所示:

SELECT * from CommonEntity LEFT OUTER JOIN Entity1 ON Entity1.refId = CommonEntity.id LEFT OUTER JOIN Entity2 ON Entity2.refId = CommonEntity.id
ORDER BY CommonField

或者你可以在你的表上创建一个视图并引入一个人工鉴别器(鉴别器可以“区分”不同表中的ID,这会导致your solution中出现问题),然后将实体映射到此视图(所以我们得到Table per class hierarchy):

CREATE VIEW EntityAandEntityB AS
SELECT 'A' as discriminator, Entity1.ID, CommonField1, ... CommonFieldZ, Entity1.field1A, ... Entity1.field1N, NULL, NULL,                          ... NULL(M)
FROM Entity1
UNION
SELECT 'B' as discriminator, Entity2.ID, CommonField1, ... CommonFieldZ, NULL, NULL,                          ... NULL(N), Entity2.field2A, ... Entity2.field2M
FROM Entity2
ORDER BY CommonField1, ...

@UdoFholl提到的其他替代方法(也是EntityAandEntityB的“外连接”)将导致2个SQL,因此无法对“整个”查询进行排序,{ {3}}

答案 2 :(得分:1)

如果您使用以下内容,Hibernate将为您执行此操作。

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractEntity implements MyInterface {
    private int someField;
}

然后让您的子类执行此操作

@Entity
@Table(name="entity_1")
public class EntityOne extends AbstractEntity {
    private int someOtherField;
}

@Entity
@Table(name="entity_2")
public class EntityTwo extends AbstractEntity {
    private int anotherSomeOtherField;
}

然后,您应该能够编写这样的查询,以便在执行排序的数据库中获得单个联合SQL查询。

FROM AbstractEntity ORDER BY someField