Java 我如何克服这个休眠限制?

Java 我如何克服这个休眠限制?,java,sql,hibernate,orm,Java,Sql,Hibernate,Orm,我在这样的层次结构中有3个实体: MyInterface | ----------------- | | Entity1 Entity2 "FROM MyInterface ORDER BY someField" MyInterface未在Hibernate中映射(因为我正在使用映射此继承) 事实上,如果我启动这样一个查询: "FROM MyInterface" 它工作

我在这样的层次结构中有3个实体:

         MyInterface
              |
      -----------------
      |               |
   Entity1          Entity2
"FROM MyInterface ORDER BY someField"
MyInterface未在Hibernate中映射(因为我正在使用映射此继承)

事实上,如果我启动这样一个查询:

"FROM MyInterface"
它工作得很好(因为它检索Entity1的所有实例和Entity2的所有实例,将它们放在一起,并返回一个
列表

如果我们看一下Hibernate生成的SQL,它将启动两个独立的SQL查询,首先检索Entity1实例,然后再检索Entity2实例,但我对此没有意见

当你尝试做这样的事情时,最大的问题来了:

         MyInterface
              |
      -----------------
      |               |
   Entity1          Entity2
"FROM MyInterface ORDER BY someField"
因为它将ORDER BY应用于第一个SQL查询,然后将相同的ORDER BY应用于第二个SQL查询,而不是将它们应用于整个查询(我知道这一点,因为我可以看到Hibernate启动的本机SQL查询)

这显然是Hibernate的错误行为


如何解决这个问题以强制Hibernate将ORDER BY应用于整个查询?(我无法在内存中执行此操作,因为稍后我还必须添加分页)。

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

我不确定在普通SQL中是否可以从2个表中读取数据并在一个查询中按2列(每个表一列)排序(这意味着没有特定于供应商的扩展),否则Hibernate将不得不在内存中进行排序


应用分页时可以做的是:只读取要排序的ID和值(而不是整个实体),然后在内存中排序,并读取页面中包含的所有ID的整个实体。要使分页保持一致,您可能必须以任何方式存储该初始查询的结果(id+顺序条件)。

您的思维方式无法按原样映射到SQL。假设您有
Entity1
和字段
field1A
field1B
。。。和
Entity2
,带有字段
field2A
field2B
。。。现在,您希望执行以下查询:

SELECT Entity1.* FROM Entity1
UNION
SELECT Entity2.* FROM Entity2
ORDER BY CommonField
这在SQL世界中是不可能的,因为实体具有不同数量的字段和不同的字段类型

因此,您需要考虑将公共字段提取到单独的表
CommonEntity
,将接口转换为独立实体,并与
Entity1
Entity2
进行一对一映射(请参阅)。那么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与不同表“区分开来”的东西,这会在中导致问题),然后将实体映射到此视图(因此我们得到):


其他备选方案(例如,
EntityAandEntityB
中提到的也是一种“外部联接”)将产生2个SQL,因此无法对“整个”查询排序,如果您使用以下选项,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;
}
然后,您应该能够编写这样的查询,以获得一个由DB进行排序的UNIONSQL查询

FROM AbstractEntity ORDER BY someField

你能提供你正在使用的映射吗?我将实体映射为独立的实体(没有什么特别的),我只是让它们成为Java级别(而不是Hibernate)MyInterface的实现者。这是一个很难简化的过程,因此我没有得到实体的映射XML,但是映射与任何其他常规实体相同,只是实现了一个公共MyInterface,没有别的。好吧,试着编写一个SQL查询,从两个不同的表中进行选择,并按公共字段排序。我认为这是不可能的,因此hibernate也不能这么做。UNION给了你一些空间。无论如何,Hibernate为HQL定义了一个语义,但由于底层技术的限制,它没有实现这些语义。我认为Hibernate在构建集合时,在
someField
上进行合并会很便宜。我是否需要额外的物理表来实现这一点?因为我无法更改基础表,所以无法添加此新表。不,这会将两个具体实体映射到它们自己的表。两个表都需要someField列,并且该列在两个表中的类型必须相同。其他列可以是特定于实体的。我的问题是,对于这种映射继承,我需要这样做,这会迫使我为实体的键使用表的相同字段名。我的表模型被锁定,表的键是相同的类型,但不是相同的名称。。。我不能使用这种映射。这是一个很好的建议。你确定你不能使用它吗?我认为可以将每个子类中的id映射到不同的字段。ID生成是限制。有关更多详细信息,请参阅。值得一试。是的,我已经试过了,您不能在子类元素中指定ID。。。遗憾的是,这听起来不错,是一个创造性的解决方案,但我会失去我需要的政治哲学,因为Entity1和Entity2都有自定义数据和行为,我需要列表来包含Entity1和Entity2的政治哲学实例…@edutesoy:我完全理解你的目标,我也很好奇,如何做到这一点,并非常惊讶地看到“解决方案”(甚至错误)。但是从不同的角度来看问题:(1)SQL不能保证行的顺序(2)当Hibernate看到行
X
时,它如何决定创建哪个实体?要解决这个问题,它需要一个鉴别器或超级实体。