我一直在尝试 HQL 和 Criteria的 不同组合,但我无法避免某些不必要的 联接 (在这两者中)和某些不必要的 选择 (在Criteria中)。
在我们的场景中, 段* 和 应用程序 实体之间具有 @ManyToMany 关系(导航是从段到应用程序)。 ***
首先,我尝试了以下 条件 :
Application app = ... List<Segment> segments = session.createCriteria(Segment.class) .createCriteria(Segment.APPLICATIONS) .add(Restrictions.idEq(app.getId())) .list();
威奇产生这个SQL:
select this_.id as id1_1_, this_.description as descript2_1_1_, this_.name as name1_1_, applicatio3_.segment_id as segment1_1_, applicatio1_.id as app2_, <==== unnecessary APPLICATIONS columns applicatio1_.id as id7_0_, applicatio1_.name as name7_0_, applicatio1_.accountId as accountId7_0_, applicatio1_.applicationFlags as applicat5_7_0_, applicatio1_.description_ as descript6_7_0_, from SEGMENTS this_ inner join SEGMENTS_APPLICATIONS applicatio3_ on this_.id=applicatio3_.segment_id inner join <==== unnecessary join APPLICATIONS applicatio1_ on applicatio3_.app_id=applicatio1_.id where applicatio1_.id = ?
如您所见, Criteria从APPLICATIONS选择列 ,我不想选择它们。我还没有找到一种方法(有可能吗?)。另外,它 与APPLICATIONS联接 ,我认为这不是必需的,因为 联接 表SEGMENTS_APPLICATIONS中已经存在应用程序ID(与HQL相同)。
(另一个疑问是,我想知道一个直接使用应用程序而不是app.getId()的限制。您将看到,我可以在查询的HQL版本中做到这一点)
由于我无法限制选择部分(不需要应用程序属性),因此我尝试使用“ select”子句来尝试此 HQL :
Application app = ... List<Segment> segments = session.createQuery( "select s from Segment s join s.applications as app where app = :app") .setParameter("app", app) .list();
产生:
select segment0_.id as id1_, segment0_.description as descript2_1_, segment0_.name as name1_, from SEGMENTS segment0_ inner join SEGMENTS_APPLICATIONS applicatio1_ on segment0_.id=applicatio1_.segment_id inner join <==== unnecessary join APPLICATIONS applicatio2_ on applicatio1_.app_id=applicatio2_.id where applicatio2_.id=?
您可以看到 HQL不会从Application中选择属性 (由于使用了“ select s”部分),但 仍会加入APPLICATIONS 表,我认为这是不必要的。我们如何避免这种情况?
(作为附带说明,请注意,在HQL中,我可以直接使用app,而不是像Criteria中那样使用app.getId())
您能帮我找到一种方法来避免标准中的“选择”和标准和HQL中不必要的“联接”吗?
(此示例与@ManyToMany一起使用,但我认为@OneToMany以及@ManyToOne和@OneToOne也会发生,即使使用fetch = LAZY也是如此)。
非常感谢,费兰
使用Criteria时,其他选定的列来自Hibernate中的一个长期存在的错误。AFAIK唯一避免这种情况的方法是使用HQL或JPA2标准API。
另一个问题也表示为bug,但影响较小,我对此不太在意。