JPA 和 Hibernate - 标准与 JPQL 或 HQL
使用标准 或 HQL? Criteria API 是在 Hibernate 中表达查询的一种很好的面向对象方式,但有时 Criteria 查询比 HQL 更难理解/构建。
什么时候使用 Criteria,什么时候使用 HQL? 在哪些用例中您更喜欢什么? 或者这只是一个品味问题?
What are the pros and cons of using Criteria or HQL? The Criteria API is a nice object-oriented way to express queries in Hibernate, but sometimes Criteria Queries are more difficult to understand/build than HQL.
When do you use Criteria and when HQL? What do you prefer in which use cases? Or is it just a matter of taste?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
HQL 可能会导致 SQL 注入等安全问题。
HQL can cause security concerns like SQL injection.
另一点是,我认为 Criteria 更适合在其之上构建,而不是在最终代码中直接使用。
与使用 jpql 或 hql 相比,它更适合使用它来构建库。
例如,我构建了 spring-data-jpa-mongodb-expressions 使用 Criteria API(与 Spring Data QBE 的方式相同)。
Another point is that, I see Criteria is more suited for building on top of it and not to be used ditectly in the end-code.
It is more suited to build liberaries using it more than using jpql or hql.
For example I've build spring-data-jpa-mongodb-expressions using Criteria API (the same way spring data QBE do).
Criteria api 提供了一项 SQL 或 HQL 都没有提供的独特功能。 IE。 它允许对查询进行编译时检查。
Criteria api provide one distinct feature that Neither SQL or HQL provides. ie. it allows compile time checking of a query.
一开始我们在应用程序中主要使用 Criteria,但由于性能问题而被 HQL 取代。
主要是我们使用非常复杂的查询和多个连接,这会导致 Criteria 中的多个查询,但在 HQL 中非常优化。
情况是我们只在特定对象上使用几个属性,而不是完整的对象。 对于 Criteria,问题还在于字符串连接。
假设您需要在 HQL 中显示用户的姓名,这非常简单
(name || ' ' || surname)
但在 Crteria 中这是不可能的。为了克服这个问题,我们使用了 ResultTransormers,其中有一些方法可以实现这种串联以获得所需的结果。
今天我们主要使用这样的 HQL:
所以在我们的例子中,返回的记录是所需属性的映射。
We used mainly Criteria in our application in the beginning but after it was replaced with HQL due to the performance issues.
Mainly we are using very complex queries with several joins which leads to multiple queries in Criteria but is very optimized in HQL.
The case is that we use just several propeties on specific object and not complete objects. With Criteria the problem was also string concatenation.
Let say if you need to display name and surname of the user in HQL it is quite easy
(name || ' ' || surname)
but in Crteria this is not possible.To overcome this we used ResultTransormers, where there were methods where such concatenation was implemented for needed result.
Today we mainly use HQL like this:
so in our case the returned records are maps of needed properties.
对我来说 Criteria 非常容易理解和进行动态查询。 但到目前为止我所说的缺陷是它加载所有多一等关系,因为我们只有三种类型的 FetchMode,即选择、代理和默认,并且在所有这些情况下它加载多一(如果有帮助,可能是我错了)我出去了:))
Criteria 的第二个问题是它加载完整的对象,即如果我只想加载员工的 EmpName,它不会出现这个,它会出现完整的 Employee 对象,因此我可以从中获取 EmpName 它在报告方面确实很糟糕。 因为 HQL 只是加载(没有加载关联/关系)你想要的东西,所以可以多次提高性能。
Criteria 的一个功能是,它可以保护您免受 SQL 注入,因为它是动态查询生成的,而在 HQL 中,您的查询要么是固定的,要么是参数化的,因此无法避免 SQL 注入。
另外,如果您在 aspx.cs 文件中编写 HQL,那么您将与 DAL 紧密耦合。
总的来说,我的结论是,有些地方没有像报告这样的 HQL 就无法生存,所以使用它们,否则 Criteria 更容易管理。
For me Criteria is a quite easy to Understand and making Dynamic queries. But the flaw i say so far is that It loads all many-one etc relations because we have only three types of FetchModes i.e Select, Proxy and Default and in all these cases it loads many-one (may be i am wrong if so help me out :))
2nd issue with Criteria is that it loads complete object i.e if i want to just load EmpName of an employee it wont come up with this insted it come up with complete Employee object and i can get EmpName from it due to this it really work bad in reporting. where as HQL just load(did't load association/relations) what u want so increase performance many times.
One feature of Criteria is that it will safe u from SQL Injection because of its dynamic query generation where as in HQL as ur queries are either fixed or parameterised so are not safe from SQL Injection.
Also if you write HQL in ur aspx.cs files, then you are tightly coupled with ur DAL.
Overall my conclusion is that there are places where u can't live without HQL like reports so use them else Criteria is more easy to manage.
对我来说,Criteria 最大的优势是示例 API,您可以在其中传递一个对象,hibernate 将根据这些对象属性构建一个查询。
除此之外,标准 API 有其怪癖(我相信 hibernate 团队正在重新设计 api),例如:
当我想要类似于 sql 的查询时,我倾向于使用 HQL(从 Status='blocked' 的用户中删除),当我不这样做时,我倾向于使用条件不想使用字符串附加。
HQL 的另一个优点是您可以预先定义所有查询,甚至可以将它们外部化到文件等中。
For me the biggest win on Criteria is the Example API, where you can pass an object and hibernate will build a query based on those object properties.
Besides that, the criteria API has its quirks (I believe the hibernate team is reworking the api), like:
I tend to use HQL when I want queries similar to sql (delete from Users where status='blocked'), and I tend to use criteria when I don't want to use string appending.
Another advantage of HQL is that you can define all your queries before hand, and even externalise them to a file or so.
这篇文章很老了。 大多数答案讨论的是 Hibernate 标准,而不是 JPA 标准。 JPA 2.1 添加了 CriteriaDelete/CriteriaUpdate 以及控制确切获取内容的 EntityGraph。 Criteria API 更好,因为 Java 是面向对象的。 这就是创建 JPA 的原因。 当JPQL被编译时,它会先被翻译成AST树(OO模型),然后再翻译成SQL。
This post is quite old. Most answers talk about Hibernate criteria, not JPA criteria. JPA 2.1 added CriteriaDelete/CriteriaUpdate, and EntityGraph that controls what exactly to fetch. Criteria API is better since Java is OO. That is why JPA is created. When JPQL is compiled, it will be translated to AST tree(OO model) before translated to SQL.
动态条件查询我们可以根据我们的输入构建查询。如果 Hql 查询是静态查询,一旦我们构建,我们就无法更改查询的结构。
Criteria query for dynamically we can construct query based on our inputs..In case of Hql query is the static query once we construct we can't change the structure of the query.
来源
source
我不想在这里踢死马,但重要的是要提到 Criteria 查询现在已被弃用。 使用 HQL。
I don't want to kick a dead horse here, but it is important to mention that Criteria queries are now deprecated. Use HQL.
我也更喜欢使用 Criteria Queries 进行动态查询。 但我更喜欢使用 hql 进行删除查询,例如,如果从父 id 'xyz' 的子表中删除所有记录,这很容易通过 HQL 实现,但对于条件 API 首先,我们必须触发 n 个删除查询,其中 n 是子项的数量表记录。
I also prefer Criteria Queries for dynamic queries. But I prefer hql for delete queries, for example if delete all records from child table for parent id 'xyz', It is easily achieved by HQL, but for criteria API first we must fire n number of delete query where n is number of child table records.
这里的大多数答案都是误导性的,并提到
Criteria Queries
比HQL
慢,但实际上并非如此。如果您深入研究并执行一些测试,您会发现标准查询的性能比常规 HQL 好得多。。
而且,通过条件查询,您可以获得面向对象的控制,这是HQL所不具备的。
有关更多信息,请阅读此处的答案。
Most the answers here are misleading and mention that
Criteria Queries
are slower thanHQL
, which is actually not the case.If you delve deep and perform some tests you will see Criteria Queries perform much better that regular HQL.
And also with Criteria Query you get Object Oriented control which is not there with HQL.
For more information read this answer here.
还有另一种方法。 我最终基于 hibernate 原始语法创建了一个 HQL 解析器,因此它首先解析 HQL,然后它可以动态注入动态参数或自动为 HQL 查询添加一些常见的过滤器。 效果很好!
There is another way. I ended up with creating a HQL parser based on hibernate original syntax so it first parse the HQL then it could dynamically inject dynamic parameters or automatically adding some common filters for the HQL queries. It works great!
要充分利用 HQL 的表达性和简洁性以及 Criteria 的动态特性,请考虑使用 Querydsl。
Querydsl 支持 JPA/Hibernate、JDO、SQL 和集合。
我是 Querydsl 的维护者,所以这个答案有偏见。
To use the best of both worlds, the expressivity and conciseness of HQL and the dynamic nature of Criteria consider using Querydsl.
Querydsl supports JPA/Hibernate, JDO, SQL and Collections.
I am the maintainer of Querydsl, so this answer is biased.
Criteria Api 是 Hibernate 的优秀概念之一。 根据我的观点,这些是我们可以区分 HQL 和 Criteria Api 的几点
Criteria Api is one of the good concept of Hibernate. according to my view these are the few point by which we can make difference between HQL and Criteria Api
条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。 HQL 没有任何方法来指定必要的提示。
您可以在这里找到更多信息:
Criteria are the only way to specify natural key lookups that take advantage of the special optimization in the second level query cache. HQL does not have any way to specify the necessary hint.
You can find some more info here:
Criteria 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。
Criteria API
Criteria API is better suited for dynamically generated queries. So, if you want to add WHERE clause filters, JOIN clauses, or vary the ORDER BY clause or the projection columns, then the Criteria API can help you generate the query dynamically in a way that also prevents SQL Injection attacks.
On the other hand, Criteria queries are less expressive and can even lead to very complicated and inefficient SQL queries.
JPQL and HQL
JPQL is the JPA standard entity query language while HQL extends JPQL and adds some Hibernate-specific features.
JPQL and HQL are very expressive and resemble SQL. Unlike Criteria API, JPQL and HQL make it easy to predict the underlying SQL query that's generated by the JPA provider. It's also much easier to review one's HQL queries than Criteria ones.
It's worth noting that selecting entities with JPQL or Criteria API makes sense if you need to modify them. Otherwise, a DTO projection is a much better choice.
Conclusion
If you don't need to vary the entity query structure, then use JPQL or HQL. If you need to change the filtering or sorting criteria or change the projection, then use Criteria API.
However, just because you are using JPA or Hibernate, it doesn't mean you should not use native SQL. SQL queries are very useful and JPQL and Criteria API are not a replacement for SQL.
Criteria是面向对象的API,而HQL意味着字符串连接。 这意味着面向对象的所有好处都适用:
由于 HQL 非常类似于 SQL(大多数开发人员已经非常了解),因此这些“不必记住”的论点没有那么重要。 如果 HQL 更加不同,那么这一点就会更加重要。
Criteria is an object-oriented API, while HQL means string concatenation. That means all of the benefits of object-orientedness apply:
Since HQL is very much like SQL (which most devs know very well already) then these "don't have to remember" arguments don't carry as much weight. If HQL was more different, then this would be more importatnt.
HQL 更易于阅读,更易于使用 Eclipse Hibernate 插件等工具进行调试,并且更易于记录。 条件查询更适合构建动态查询,其中许多行为是在运行时确定的。 如果您不懂 SQL,我可以理解使用 Criteria 查询,但总的来说,如果我预先知道自己想要什么,我更喜欢 HQL。
HQL is much easier to read, easier to debug using tools like the Eclipse Hibernate plugin, and easier to log. Criteria queries are better for building dynamic queries where a lot of the behavior is determined at runtime. If you don't know SQL, I could understand using Criteria queries, but overall I prefer HQL if I know what I want upfront.
当我不知道输入将用于哪些数据时,我通常使用 Criteria。 就像在搜索表单上一样,用户可以输入 1 到 50 个项目中的任何一个,但我不知道他们要搜索什么。 当我检查用户正在搜索的内容时,很容易在条件中添加更多内容。 我觉得这种情况下放HQL查询会比较麻烦一点。 当我确切地知道我想要什么时,HQL 很棒。
I usually use Criteria when I don't know what the inputs will be used on which pieces of data. Like on a search form where the user can enter any of 1 to 50 items and I don't know what they will be searching for. It is very easy to just append more to the criteria as I go through checking for what the user is searching for. I think it would be a little more troublesome to put an HQL query in that circumstance. HQL is great though when I know exactly what I want.
我最喜欢动态查询的条件查询。 例如,根据某些参数动态添加一些排序或保留某些部分(例如限制)要容易得多。
另一方面,我使用 HQL 进行静态和复杂的查询,因为它更容易理解/阅读 HQL。 另外,我认为 HQL 更强大一些,例如对于不同的连接类型。
I mostly prefer Criteria Queries for dynamic queries. For example it is much easier to add some ordering dynamically or leave some parts (e.g. restrictions) out depending on some parameter.
On the other hand I'm using HQL for static and complex queries, because it's much easier to understand/read HQL. Also, HQL is a bit more powerful, I think, e.g. for different join types.
HQL 和 criteriaQuery 之间在性能方面存在差异,每次使用 criteriaQuery 触发查询时,它都会为表名创建一个新别名,该别名不会反映在任何数据库的最后查询缓存中。 这会导致编译生成的 SQL 的开销,从而需要更多的时间来执行。
关于获取策略[http://www.hibernate.org/315.html]
There is a difference in terms of performance between HQL and criteriaQuery, everytime you fire a query using criteriaQuery, it creates a new alias for the table name which does not reflect in the last queried cache for any DB. This leads to an overhead of compiling the generated SQL, taking more time to execute.
Regarding fetching strategies [http://www.hibernate.org/315.html]