java - JPA和Hibernate - Criteria与JPQL或HQL
使用Criteria或HQL有哪些优缺点? Criteria API是一种很好的面向对象的方式来表达Hibernate中的查询,但有时Criteria Queries比HQL更难理解/构建。
什么时候使用Criteria和何时使用HQL? 您更喜欢哪种用例? 或者只是品味问题?
21个解决方案
202 votes
我更喜欢Criteria Queries来进行动态查询。 例如,根据某些参数,动态添加一些排序或保留一些部分(例如限制)要容易得多。
另一方面,我使用HQL进行静态和复杂查询,因为它更容易理解/读取HQL。 另外,我认为HQL更强大,例如 对于不同的连接类型。
cretzel answered 2019-02-03T19:28:24Z
88 votes
HQL和criteriaQuery之间的性能存在差异,每次使用criteriaQuery触发查询时,它都会为表名创建一个新别名,该别名不反映在任何数据库的最后查询缓存中。 这导致编译生成的SQL的开销,花费更多的时间来执行。
关于获取策略[[http://www.hibernate.org/315.html]]
Criteria尊重映射中的惰性设置,并保证加载您想要加载的内容。 这意味着一个Criteria查询可能会导致多个SQL立即SELECT语句获取具有所有非延迟映射关联和集合的子图。 如果要更改“how”甚至“what”,请使用setFetchMode()为特定集合或关联启用或禁用外部联接提取。 Criteria查询也完全尊重提取策略(join vs select vs subselect)。
HQL尊重映射中的延迟设置,并保证加载要加载的内容。 这意味着一个HQL查询可能会导致多个SQL立即SELECT语句获取具有所有非延迟映射关联和集合的子图。 如果要更改“how”甚至“what”,请使用LEFT JOIN FETCH为特定集合启用外部联接提取,或者为可以多对一或一对一关联的可空连接,或使用JOIN FETCH启用 内部联接获取非可空的多对一或一对一关联。 HQL查询不遵循映射文档中定义的任何fetch =“join”。
Varun Mehta answered 2019-02-03T19:29:08Z
38 votes
Criteria是面向对象的API,而HQL意味着字符串连接。 这意味着面向对象的所有好处都适用:
在其他条件相同的情况下,OO版本不太容易出错。 任何旧字符串都可以附加到HQL查询中,而只有有效的Criteria对象才能将其添加到Criteria树中。 实际上,Criteria类更受限制。
通过自动完成,OO更容易被发现(因此至少对我来说更容易使用)。 您不一定需要记住查询的哪些部分在哪里; IDE可以帮助你
您也不需要记住语法的细节(比如哪些符号去哪里)。 您需要知道的是如何调用方法和创建对象。
由于HQL非常像SQL(大多数开发人员已经非常熟悉),因此这些“不必记住”的参数不会带来太大的影响。 如果HQL更加不同,那么这将更加重要。
Craig Walker answered 2019-02-03T19:29:57Z
34 votes
当我不知道哪些输入将用于哪些数据时,我通常使用Criteria。 就像在搜索表单上,用户可以输入1到50个项目中的任何一个,我不知道他们将要搜索什么。 当我检查用户正在搜索的内容时,很容易在标准上添加更多内容。 我认为在这种情况下放置HQL查询会有点麻烦。 当我确切地知道我想要什么时,HQL很棒。
Arthur Thomas answered 2019-02-03T19:30:20Z
31 votes
HQL更容易阅读,使用Eclipse Hibernate插件等工具更容易调试,更容易记录。 Criteria查询更适合构建动态查询,其中许多行为是在运行时确定的。 如果您不了解SQL,我可以理解使用Criteria查询,但总体而言,如果我知道我想要的是什么,我更喜欢HQL。
Brian Deterling answered 2019-02-03T19:30:42Z
22 votes
条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。 HQL没有任何方法来指定必要的提示。
你可以在这里找到更多信息:
[http://tech.puredanger.com/2009/07/10/hibernate-query-cache/]
Alex Miller answered 2019-02-03T19:31:17Z
20 votes
Criteria Api是Hibernate的一个很好的概念。 根据我的观点,这些是我们可以在HQL和Criteria Api之间做出改动的几点
HQL是对数据执行选择和非选择操作,但Criteria仅用于选择数据,我们不能使用条件执行非选择操作。
HQL适用于执行静态查询,其中Criteria适合执行动态查询
HQL不支持分页概念,但我们可以使用Criteria实现分页。
标准用于执行比HQL更多的时间。
使用Criteria我们可以安全地使用SQL注入因为它的动态查询生成,但是在HQL中,因为您的查询是固定的或参数化的,所以SQL注入没有安全性
Arvind answered 2019-02-03T19:32:12Z
13 votes
对我而言,Criteria非常容易理解和制作动态查询。 但我到目前为止所说的缺陷是它加载了所有多个等关系,因为我们只有三种类型的FetchModes,即Select,Proxy和Default,在所有这些情况下它加载了多个(如果有帮助,可能是我错了) 我:))
Criteria的第二个问题是它加载了完整的对象,即如果我只想加载一个员工的EmpName,它就不会想出它提出完整的Employee对象,我可以从中获取EmpName,因为它真的很糟糕报告。 HQL只是加载(没有加载关联/关系)你想要的,所以多次提高性能。
Criteria的一个特性是它可以安全地使用SQL注入,因为它的动态查询生成在HQL中,因为ur查询是固定的或参数化的,所以从SQL注入是不安全的。
另外,如果你在ur aspx.cs文件中编写HQL,那么你就与你的DAL紧密结合了。
总的来说,我的结论是,有些地方,如果没有像报告这样的HQL,你就无法生存。所以使用其他标准更容易管理。
Zafar answered 2019-02-03T19:33:00Z
12 votes
为了充分利用这两方面的优势,HQL的表现力和简洁性以及Criteria的动态性质考虑使用Querydsl。
Querydsl支持JPA / Hibernate,JDO,SQL和Collections。
我是Querydsl的维护者,所以这个答案是有偏见的。
Timo Westkämper answered 2019-02-03T19:33:35Z
11 votes
对我来说,Criteria上最大的胜利是Example API,你可以在其中传递一个对象,而hibernate将根据这些对象属性构建一个查询。
除此之外,标准API有其怪癖(我相信hibernate团队正在重新编写api),如:
criteria.createAlias(“obj”)强制内部联接而不是可能的外部联接
你不能两次创建相同的别名
一些sql子句没有简单的标准对应物(如子选择)
等等
当我想要类似于sql的查询时,我倾向于使用HQL(从status ='blocked'的用户中删除),当我不想使用字符串追加时,我倾向于使用条件。
HQL的另一个优点是您可以事先定义所有查询,甚至可以将它们外部化到文件中。
Miguel Ping answered 2019-02-03T19:34:37Z
9 votes
Criteria api提供了SQL或HQL都不提供的一个独特功能。即。 它允许编译时检查查询。
user1165443 answered 2019-02-03T19:35:00Z
9 votes
在运行时动态应用查询过滤器时,Criteria API更适合动态生成的查询。 因此,为了在构建动态查询时防止SQL注入攻击,Criteria API是一个非常好的选择。
Criteria查询的表达性较差,您可以轻松地使用非常复杂且低效的SQL生成查询。 我曾经加入了一个大型企业应用程序,其中Criteria API是默认的查询方法,甚至没有广泛的代码审查可以克服不知道我们最终会得到什么SQL查询的恐怖。
JPQL或HQL更具表现力,预测相关生成的SQL查询要容易得多。 查看一个HQL查询比使用标准查询要容易得多。
大多数实体查询用例不需要动态where子句,因此您可以使用JPQL实现大多数查询,同时保留动态的Criteria。
值得注意的是,如果您需要修改它们,选择具有JPQL或Criteria API的实体是有意义的。 否则,DTO投影表现更好。 查看此文章了解更多信息。
Vlad Mihalcea answered 2019-02-03T19:35:48Z
7 votes
在我们的应用程序中,我们主要使用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();
所以在我们的例子中,返回的记录是所需属性的映射。
Bojan Kraut answered 2019-02-03T19:36:49Z
7 votes
HQL是对数据执行选择和非选择操作,但Criteria仅用于选择数据,我们不能使用条件执行非选择操作
HQL适用于执行静态查询,其中Criteria适合执行动态查询
HQL不支持分页概念,但我们可以使用Criteria实现分页
标准过去需要花费更多时间来执行HQL
使用Criteria,我们可以安全地使用SQL注入因为它的动态查询生成,但是在HQL中,因为您的查询是固定的或参数化的,所以SQL注入没有安全性。
资源
Premraj answered 2019-02-03T19:37:39Z
5 votes
Criteria查询动态我们可以根据我们的输入构造查询。如果Hql查询是静态查询,一旦我们构造我们就无法改变查询的结构。
user1679378 answered 2019-02-03T19:38:01Z
4 votes
我不想在这里踢死马,但重要的是要提到Criteria查询现已弃用。 使用HQL。
Eskir answered 2019-02-03T19:38:23Z
1 votes
我也更喜欢Criteria Queries进行动态查询。 但我更喜欢使用hql进行删除查询,例如,如果从子表中删除父ID为'xyz'的所有记录,则可以通过HQL轻松实现,但对于标准API,我们必须首先触发n个删除查询,其中n是子数 表记录。
Punit Patel answered 2019-02-03T19:38:45Z
0 votes
这里的大多数答案都是误导性的,并提到Criteria Queries比HQL慢,实际情况并非如此。
如果深入研究并执行一些测试,您会发现Criteria Queries的性能比常规HQL好得多。
而且使用Criteria Query,您可以获得面向对象的控件,这与HQL不同。
有关更多信息,请阅读此答案。
Pritam Banerjee answered 2019-02-03T19:39:26Z
0 votes
还有另一种方式。 我最终创建了一个基于hibernate原始语法的HQL解析器,因此它首先解析HQL然后它可以动态注入动态参数或自动为HQL查询添加一些常见的过滤器。 它很棒!
Wallace Peng answered 2019-02-03T19:39:48Z
0 votes
这篇文章很老了。 大多数答案都是关于Hibernate标准,而不是JPA标准。 JPA 2.1添加了CriteriaDelete / CriteriaUpdate,以及控制究竟要获取内容的EntityGraph。 Criteria API更好,因为Java是OO。 这就是创建JPA的原因。 编译JPQL时,在转换为SQL之前,它将被转换为AST树(OO模型)。
Sunnyday answered 2019-02-03T19:40:11Z
-3 votes
HQL可能导致SQL注入等安全问题。
Emad Aghayi answered 2019-02-03T19:40:33Z