【问题标题】:Convert HQL query in the form of "select foo from Foo foo, Bar bar where ..." to Criteria query将“select foo from Foo foo, Bar bar where ...”形式的HQL查询转换为Criteria查询
【发布时间】:2020-02-02 13:05:04
【问题描述】:

在我们的(古老的)项目中,我们在 Hibernate 版本 3.5.6-Final 上使用了大量带有 HQL 的选择查询。因为 Hibernate 将执行自动提交,因为它不知道它们是选择查询,所以我正在将所有 HQL 选择查询重写为 Hibernate Criteria 查询,因此当我们不这样做时它不会执行中间提交还不想要。在大多数情况下,这非常简单,但我目前正在查看这样的查询,但我不确定如何转换它:

Query query = session.createQuery("select municapilityStreet"
  + " from MunicapilityStreet munStreet, Street street"
  + " where munStreet.id = street.MunicapilityStreet.id"
  + " and street.id = :streetId");
query.setParameter(":streetId", streetId);
MunicapilityStreet result = (MunicapilityStreet) query.uniqueResult();
return result;

这是我迄今为止在改造它的过程中所拥有的:

Criteria criteria = session.createCriteria(MunicapilityStreet.class);

// No idea what to set here to only get the "municapilityStreet" as result
criteria.setProjection(??);

// I'm not sure if this is correct. With a criteria on a single table it would have been simply "Id".
// Both tables have the column-name Id, and I'm not sure how to differentiate between them.
criteria.add(Restrictions.eq("Street.Id", streetId));

MunicapilityStreet result = (MunicapilityStreet) criteria.uniqueResult();
return result;

也许我应该为每个问题创建一个不同的问题,但是将上述 HQL 查询转换为 Criteria 有三点我不知道该怎么做:

  1. 如何对多个表进行选择(from MunicapilityStreet munStreet, Street street 部分)?
  2. 如何进行投影以仅返回两者中的一个表(select municapilityStreet 部分)?
  3. 如何对一个表的列名设置相等限制,即使两个表具有相同的列名(and street.id = :streetId 部分)?

【问题讨论】:

    标签: java hibernate select hql hibernate-criteria


    【解决方案1】:

    我确实反对重写方法,我希望我这样做不是不礼貌的。

    Hibernate 允许控制提交(自动提交默认关闭),而您遇到的是 Entitymanager-flushes,默认情况下它们是自动的,可以是 disabled too。最后,我认为,如果您运行 HQL 或标准查询,底层的机器相同,则没有区别。

    【讨论】:

    • 是否可以仅对某些查询禁用自动提交,而不是一般情况下?如果我完全禁用自动提交,我相信事情会中断。它可能会解决我当前的问题,但可能会在预期刷新但不再发生的其他地方引起问题。这个项目的问题在于它自 2008 年以来一直处于活跃状态,几乎没有任何文档、cmets 或 git 消息(除了最近约 3 年)。所以重写查询更容易验证我没有破坏其他任何东西,然后一起禁用自动提交。如果我可以在每个查询中禁用它,那就太好了!
    • 因为实体管理器应该被使用 [单线程] (stackoverflow.com/questions/20997410/…) 你应该能够在每个查询的基础上禁用它(禁用,重新启用)。我曾经遇到过类似的事情,据我所知,做到了。不在保修范围内;-) 但测试比重写所有查询要快得多。
    • Hibernate 在使用 Criterias 进行选择查询时不会自动刷新,但是在使用 HQL 时,Hibernate 不知道它是否是一个选择/更新/删除/等,所以它总是会这样做使用本机查询自动刷新。至少,这是我从我的高级同事那里了解到的,并且在查看 Hibernate 源代码时是这样理解的。 (PS:也许也相关:我们正在使用 Hibernate 版本 3.5.6-Final - 显然。)
    • 带有session.createQuery("some query") 的是HQL,对(至少,上面的文档声明为给定的HQL 查询字符串创建一个新的Query 实例。)?所以你说Hibernate应该能够用session.createQuery("some query")判断它是什么类型的查询,并且当它是session.createQuery("select ... from ...")session.createQuery("from ...")时不应该自动刷新?如果它应该基于字符串知道,那么在这种情况下我们现在得到的两次刷新之间不需要的原因可能是什么?我应该在代码中的哪里搜索?
    • 没错,says the spec,但它们不是本地的 (says the spec)。如果你确定你的主张,我现在手头上没有任何东西可以反驳你。无论如何,可以显式禁用自动刷新。
    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 2017-06-23
    相关资源
    最近更新 更多