309

使用CriteriaHQL的优缺点是什么?Criteria API 是在 Hibernate 中表达查询的一种很好的面向对象的方式,但有时 Criteria Queries 比 HQL 更难理解/构建。

您什么时候使用 Criteria,什么时候使用 HQL?在哪些用例中你更喜欢什么?还是只是口味问题?

4

22 回答 22

219

我最喜欢动态查询的条件查询。例如,根据某些参数动态添加一些排序或保留一些部分(例如限制)要容易得多。

另一方面,我将 HQL 用于静态和复杂查询,因为它更容易理解/阅读 HQL。此外,我认为 HQL 更强大一些,例如对于不同的连接类型。

于 2008-10-13T12:54:37.357 回答
93

HQL 和criteriaQuery 在性能方面存在差异,每次使用criteriaQuery 触发查询时,它都会为表名创建一个新别名,该别名不会反映在任何数据库的最后查询缓存中。这会导致编译生成的 SQL 的开销,需要更多时间来执行。

关于获取策略[http://www.hibernate.org/315.html]

  • Criteria 尊重映射中的惰性设置,并保证加载您想要加载的内容。这意味着一个 Criteria 查询可能会导致几个 SQL 立即 SELECT 语句来获取具有所有非延迟映射关联和集合的子图。如果您想更改“如何”甚至“什么”,请使用 setFetchMode() 启用或禁用特定集合或关联的外连接获取。条件查询也完全尊重获取策略(join vs select vs subselect)。
  • HQL 尊重映射中的惰性设置,并保证加载您想要加载的内容。这意味着一个 HQL 查询可能会导致几个 SQL 立即 SELECT 语句来获取具有所有非延迟映射关联和集合的子图。如果要更改“如何”甚至“什么”,请使用 LEFT JOIN FETCH 为特定集合或可为空的多对一或一对一关联启用外连接获取,或使用 JOIN FETCH 启用内部连接获取不可为空的多对一或一对一关联。HQL 查询不尊重映射文档中定义的任何 fetch="join"。
于 2008-12-04T17:30:58.353 回答
42

Criteria 是面向对象的 API,而 HQL 表示字符串连接。这意味着面向对象的所有好处都适用:

  1. 在其他条件相同的情况下,OO 版本不太容易出错。任何旧字符串都可以附加到 HQL 查询中,而只有有效的 Criteria 对象才能将其添加到 Criteria 树中。实际上,Criteria 类受到更多限制。
  2. 通过自动完成,OO 更容易被发现(因此更容易使用,至少对我而言)。您不一定需要记住查询的哪些部分在哪里;IDE 可以帮助您
  3. 你也不需要记住语法的细节(比如哪些符号去哪里)。您只需要知道如何调用方法和创建对象。

由于 HQL 非常类似于 SQL(大多数开发人员已经非常了解),因此这些“不必记住”的论点就没有那么重要了。如果 HQL 更不同,那么这将更重要。

于 2008-10-13T14:42:18.013 回答
37

当我不知道哪些输入将用于哪些数据时,我通常使用 Criteria。就像在用户可以输入 1 到 50 个项目中的任何一个的搜索表单上一样,我不知道他们将要搜索什么。当我检查用户正在搜索的内容时,很容易将更多内容附加到标准中。我认为在这种情况下放置 HQL 查询会有点麻烦。当我确切地知道我想要什么时,HQL 很棒。

于 2008-10-13T22:07:33.123 回答
33

HQL 更易于阅读,更易于使用 Eclipse Hibernate 插件等工具进行调试,并且更易于记录。标准查询更适合构建动态查询,其中很多行为是在运行时确定的。如果你不懂 SQL,我可以理解使用 Criteria 查询,但总的来说,如果我知道我想要什么,我更喜欢 HQL。

于 2008-10-13T15:28:07.767 回答
24

条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。HQL 没有任何方法来指定必要的提示。

您可以在此处找到更多信息:

于 2009-07-10T07:21:51.140 回答
23

Criteria Api 是 Hibernate 的优秀概念之一。根据我的观点,这些是我们可以在HQLCriteria Api之间有所不同的几点

  1. HQL 是对数据进行选择和非选择操作,但 Criteria 仅用于选择数据,我们不能使用条件进行非选择操作。
  2. HQL 适合执行静态查询,而 Criteria 适合执行动态查询
  3. HQL 不支持分页概念,但是我们可以通过 Criteria 实现分页。
  4. 标准过去比 HQL 需要更多的时间来执行。
  5. 使用 Criteria,我们可以安全使用SQL 注入,因为它会生成动态查询,但在 HQL 中,因为您的查询要么是固定的,要么是参数化的,因此 SQL 注入是不安全的
于 2013-05-08T07:48:57.777 回答
21

标准 API

Criteria API 更适合动态生成的查询。因此,如果您想添加 WHERE 子句过滤器、JOIN 子句或改变 ORDER BY 子句或投影列,那么 Criteria API 可以帮助您以一种同时防止 SQL 注入攻击的方式动态生成查询。

另一方面,Criteria 查询的表达能力较差,甚至会导致非常复杂和低效的 SQL 查询。

JPQL 和 HQL

JPQL 是 JPA 标准实体查询语言,而 HQL 扩展了 JPQL 并添加了一些特定于 Hibernate 的特性。

JPQL 和 HQL 非常具有表现力,并且类似于 SQL。与 Criteria API 不同,JPQL 和 HQL 可以轻松预测 JPA 提供程序生成的底层 SQL 查询。审查 HQL 查询也比 Criteria 查询容易得多。

值得注意的是,如果您需要修改它们,那么使用 JPQL 或 Criteria API 选择实体是有意义的。否则,DTO 投影是更好的选择。

结论

如果您不需要改变实体查询结构,则使用 JPQL 或 HQL。如果您需要更改过滤或排序标准或更改投影,请使用 Criteria API。

但是,仅仅因为您使用的是 JPA 或 Hibernate,并不意味着您不应该使用本机 SQL。SQL 查询非常有用,JPQL 和 Criteria API 不能替代 SQL。

于 2014-11-09T07:22:50.563 回答
15

要使用两全其美,HQL 的表现力和简洁性以及 Criteria 的动态特性考虑使用Querydsl

Querydsl 支持 JPA/Hibernate、JDO、SQL 和集合。

我是Querydsl的维护者,所以这个答案是有偏见的。

于 2010-01-11T21:01:56.540 回答
14

对我来说,Criteria 是一个很容易理解和进行动态查询的方法。但到目前为止我说的缺陷是它加载了所有多一等关系,因为我们只有三种类型的 FetchMode,即选择、代理和默认,并且在所有这些情况下它加载多一(如果有帮助,我可能错了我出去:))

Criteria 的第二个问题是它加载了完整的对象,即如果我只想加载员工的 EmpName,它不会想出这个 insted 它会提供完整的 Employee 对象,因此我可以从中获取 EmpName,因为它真的很糟糕报告。HQL 只是加载(没有加载关联/关系)你想要的东西,所以性能会提高很多倍。

Criteria 的一个特点是它可以保护你免受 SQL 注入的影响,因为它的动态查询生成方式与在 HQL 中一样,因为你的查询要么是固定的,要么是参数化的,因此对 SQL 注入不安全。

此外,如果您在您的 aspx.cs 文件中编写 HQL,那么您将与您的 DAL 紧密耦合。

总的来说,我的结论是,有些地方没有 HQL 之类的报告就无法生存,因此请使用它们,否则标准更易于管理。

于 2009-07-06T12:09:05.183 回答
12

对我来说,Criteria 的最大胜利是 Example API,您可以在其中传递一个对象,hibernate 将基于这些对象属性构建一个查询。

除此之外,标准 API 有其怪癖(我相信 hibernate 团队正在重新设计 api),例如:

  • 一个 criteria.createAlias("obj") 强制内部联接而不是可能的外部联接
  • 您不能两次创建相同的别名
  • 一些 sql 子句没有简单的条件对应项(如子选择)
  • 等等

当我想要类似于 sql 的查询(从用户中删除 status='blocked')时,我倾向于使用 HQL,而当我不想使用字符串附加时,我倾向于使用条件。

HQL 的另一个优点是您可以预先定义所有查询,甚至可以将它们外部化到一个文件左右。

于 2008-10-14T12:56:33.423 回答
9

我们一开始在我们的应用程序中主要使用 Criteria,但后来由于性能问题将其替换为 HQL。
主要是我们使用具有多个连接的非常复杂的查询,这会导致 Criteria 中的多个查询,但在 HQL 中非常优化。
情况是我们只在特定对象上使用了几个属性,而不是完整的对象。对于 Criteria,问题也是字符串连接。
假设您需要在 HQL 中显示用户的姓名和姓氏,这很容易(name || ' ' || surname),但在 Crteria 中这是不可能的。
为了克服这个问题,我们使用了 ResultTransormers,其中有一些方法可以实现这种连接以获得所需的结果。
今天我们主要是这样使用HQL:

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

所以在我们的例子中,返回的记录是所需属性的映射。

于 2012-01-09T22:43:00.107 回答
9

Criteria api 提供了 SQL 或 HQL 都没有提供的一项独特功能。IE。它允许对查询进行编译时检查。

于 2012-01-23T17:12:14.237 回答
7
  • HQL是对数据进行select和non-select操作,但是Criteria只是对数据进行选择,我们不能使用criteria进行non-select操作
  • HQL 适合执行静态查询,而 Criteria 适合执行动态查询
  • HQL不支持分页概念,但是我们可以用Criteria实现分页
  • 标准过去比 HQL 需要更多时间来执行
  • 使用 Criteria,我们可以安全地使用 SQL 注入,因为它会生成动态查询,但在 HQL 中,由于您的查询是固定的或参数化的,因此 SQL 注入没有安全性。

来源

于 2015-12-05T01:14:13.663 回答
6

动态的条件查询我们可以根据我们的输入构造查询。如果 Hql 查询是静态查询,一旦我们构造我们就不能改变查询的结构。

于 2013-01-25T06:54:06.053 回答
5

我不想在这里踢死马,但重要的是要提到现在不推荐使用 Criteria 查询。使用 HQL。

于 2016-09-14T08:48:21.913 回答
1

对于动态查询,我也更喜欢 Criteria Queries。但是我更喜欢使用 hql 进行删除查询,例如,如果从子表中删除父 id 'xyz' 的所有记录,这很容易通过 HQL 实现,但是对于标准 API,我们必须首先触发 n 个删除查询,其中 n 是子表的数量表记录。

于 2013-06-18T09:36:06.270 回答
0

这里的大多数答案都具有误导性,并提到Criteria Queries比 慢HQL,实际上并非如此。

如果您深入研究并执行一些测试,您会发现Criteria Queries 比常规 HQL 执行得更好

此外,使用Criteria Query您可以获得HQL所没有的面向对象控制

有关更多信息,请在此处阅读此答案。

于 2016-07-18T23:51:50.150 回答
0

还有另一种方法。我最终创建了一个基于 hibernate 原始语法的 HQL 解析器,因此它首先解析 HQL,然后它可以动态注入动态参数或为 HQL 查询自动添加一些常用过滤器。效果很好!

于 2018-01-12T19:00:38.133 回答
0

这个帖子很老了。大多数答案都是关于 Hibernate 标准,而不是 JPA 标准。JPA 2.1 添加了 CriteriaDelete/CriteriaUpdate 和 EntityGraph 来控制要获取的确切内容。Criteria API 更好,因为 Java 是 OO。这就是创建 JPA 的原因。JPQL 在编译时会先翻译成 AST 树(OO 模型),然后再翻译成 SQL。

于 2018-04-25T03:45:25.023 回答
0

另一点是,我认为 Criteria 更适合在它之上构建,而不是在最终代码中单独使用。

它比使用 jpql 或 hql 更适合使用它来构建库。

例如,我使用 Criteria API 构建了 spring-data-jpa-mongodb-expressions(与 spring data QBE 一样)。

我认为 spring 数据查询生成使用 jpaql 而不是我不明白为什么的标准。

于 2021-05-18T21:46:14.030 回答
-3

HQL 可能会导致SQL 注入等安全问题。

于 2013-05-06T05:57:45.940 回答