当前位置: 首页 > 知识库问答 >
问题:

如何避免HQL和Criteria中不必要的选择和连接

秦鸿羽
2023-03-14

我一直在尝试HQL和Criteria的不同组合,但我无法避免一些不必要的连接(在两者中)和一些不必要选择(在Criteria中)。

在我们的场景中,我们在Segment和Application实体之间有@ManyTo的关系(导航是从Segment到应用程序)。

首先我尝试了这个标准:

Application app = ...
List<Segment> segments = session.createCriteria(Segment.class)
    .createCriteria(Segment.APPLICATIONS)
    .add(Restrictions.idEq(app.getId()))
    .list();

Wich 生成此 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从APPLICATION中选择列,我不想被选择。我还没有找到做这件事的方法(有可能吗?)。此外,它与application连接,我认为这是不必要的,因为应用程序id已经在连接表SEGMENTS_application中(HQL也是如此)。

(作为附加疑问,我想知道一个直接使用app的限制,而不是app.getId()。正如您将看到的,我可以在HQL版本的查询中这样做)

由于我无法限制select部分(我不需要Application属性),我尝试了使用“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();

wich产生:

html" target="_blank">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 没有从应用程序中选择属性(感谢“选择 s”部分),但仍然加入 APPLICATIONS 表,我认为这是不必要的。我们怎样才能避免这种情况?

(作为旁注,注意在HQL我可以直接使用app,而不是像标准中那样使用app.getId()

你能帮我找到一种方法来避免条件中的“选择”和标准和 HQL 中不必要的“连接”吗?

(这个例子是关于@ManyToMany的,但我认为它也发生在@OneToMany以及@ManyToOne和@OneToOne上,甚至fetch = LAZY)。

非常感谢你,费兰

共有1个答案

陶智
2023-03-14

使用条件时额外选择的列来自Hibernate中一个长期存在的错误。AFAIK,避免它的唯一方法是使用HQL,或JPA2标准API。

另一个问题也被认为是一个bug,但它的影响较小,我不会太在意它。

 类似资料:
  • 问题内容: 我一直在尝试 HQL 和 Criteria的 不同组合,但我无法避免某些不必要的 联接 (在这两者中)和某些不必要的 选择 (在Criteria中)。 在我们的场景中, 段* 和 应用程序 实体之间具有 @ManyToMany 关系(导航是从段到应用程序)。 *** 首先,我尝试了以下 条件 : 威奇产生这个SQL: 如您所见, Criteria从APPLICATIONS选择列 ,我不

  • 本文向大家介绍在React中如何避免不必要的render?相关面试题,主要包含被问及在React中如何避免不必要的render?时的应答技巧和注意事项,需要的朋友参考一下 shouldComponentUpdate、memoization、PureComponent

  • 问题内容: 我在优化Hibernate查询以免执行联接或辅助选择时遇到了麻烦。 执行Hibernate查询(条件或hql)时,例如: …,而where子句检查不需要与其他表进行任何联接的属性…,但是Hibernate仍与其他表进行完全联接(或辅助选择,具体取决于我如何设置fetchMode)。 有问题的对象(GiftCard)有几个ManyToOne关联,在这种情况下(但不一定是所有情况),我希望

  • 问题内容: 我有一个GUI,可根据滑块值向Web服务器发布命令。其中一些滑块是“耦合”在Web服务器上的,因此更改其中一个也可能会更改另一个。通过Web服务器返回基于发出的命令设置的值的列表来完成耦合。 因此,我可以根据此响应轻松设置适当的滑块,但问题是这样做会导致ChangeListener被触发,然后再次向Web服务器发出命令。理想情况下,“耦合”应表现良好,并避免无限循环,但这是一个潜在问题

  • 问题内容: 我有几个较旧的应用程序,它们在E_NOTICE错误级别上运行时会抛出很多“ xyz未定义”和“未定义偏移”消息,因为没有使用和明确检查变量的存在。 我正在考虑通过它们使它们与E_NOTICE兼容,因为有关丢失变量或偏移量的通知可能会节省生命,可能会获得一些较小的性能改进,并且总体而言,这是一种更清洁的方法。 但是,我不喜欢什么造成数百 和S ^确实给我的代码。它变得肿,可读性降低,而没

  • 我有一个Java servlet,它从android应用程序中获取一些数据,并使用以下代码将字符串数据返回给android应用程序。 然后使用以下方法将该值转换为字符串: 但是这样做之后,结果会添加一些不需要的字符(它们在菱形中以“?”的形式出现)附加到我从servlet传递的原始字符串中。我怎样才能避免这个?