Java JPA 和 Hibernate - 标准与 JPQL 或 HQL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/197474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA and Hibernate - Criteria vs. JPQL or HQL
提问by cretzel
What are the pros and cons of using Criteriaor 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.
使用Criteria或HQL 的优缺点是什么?Criteria API 是在 Hibernate 中表达查询的一种很好的面向对象的方式,但有时 Criteria Queries 比 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?
什么时候使用 Criteria,什么时候使用 HQL?您更喜欢哪些用例?还是只是口味问题?
采纳答案by cretzel
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 用于静态和复杂查询,因为它更容易理解/阅读 HQL。此外,我认为 HQL 更强大一些,例如对于不同的连接类型。
回答by Craig Walker
Criteria is an object-oriented API, while HQL means string concatenation. That means all of the benefits of object-orientedness apply:
Criteria 是面向对象的 API,而 HQL 表示字符串连接。这意味着面向对象的所有好处都适用:
- All else being equal, the OO version is somewhat less prone to error. Any old string could get appended into the HQL query, whereas only valid Criteria objects can make it into a Criteria tree. Effectively, the Criteria classes are more constrained.
- With auto-complete, the OO is more discoverable (and thus easier to use, for me at least). You don't necessarily need to remember which parts of the query go where; the IDE can help you
- You also don't need to remember the particulars of the syntax (like which symbols go where). All you need to know is how to call methods and create objects.
- 在其他条件相同的情况下,OO 版本不太容易出错。任何旧字符串都可以附加到 HQL 查询中,而只有有效的 Criteria 对象才能将其放入 Criteria 树中。实际上,Criteria 类受到更多限制。
- 通过自动完成,OO 更容易被发现(因此更容易使用,至少对我来说)。您不一定需要记住查询的哪些部分去哪里;IDE 可以帮助您
- 你也不需要记住语法的细节(比如哪些符号去哪里)。您只需要知道如何调用方法和创建对象。
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 与 SQL 非常相似(大多数开发人员已经非常了解),因此这些“不必记住”的论点没有那么重要。如果 HQL 更不同,那么这将更重要。
回答by Brian Deterling
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.
HQL 更易于阅读、更易于使用 Eclipse Hibernate 插件等工具进行调试,并且更易于记录。条件查询更适合构建动态查询,其中许多行为是在运行时确定的。如果您不知道 SQL,我可以理解使用 Criteria 查询,但总的来说,如果我预先知道我想要什么,我更喜欢 HQL。
回答by Arthur Thomas
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 dunno 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.
当我不知道哪些输入将用于哪些数据时,我通常会使用 Criteria。就像在搜索表单上,用户可以输入 1 到 50 个项目中的任何一个,我不知道他们会搜索什么。当我检查用户正在搜索的内容时,很容易将更多内容附加到条件中。我认为在这种情况下放置 HQL 查询会更麻烦一些。HQL 很棒,但当我确切地知道我想要什么时。
回答by Miguel Ping
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.
对我来说,Criteria 的最大优势是 Example API,您可以在其中传递一个对象,hibernate 将根据这些对象属性构建查询。
Besides that, the criteria API has its quirks (I believe the hibernate team is reworking the api), like:
除此之外,标准 API 有其怪癖(我相信休眠团队正在重新设计 api),例如:
- a criteria.createAlias("obj") forces a inner join instead of a possible outer join
- you can't create the same alias two times
- some sql clauses have no simple criteria counterpart (like a subselect)
- etc.
- 一个criteria.createAlias("obj") 强制一个内部连接而不是一个可能的外部连接
- 您不能两次创建相同的别名
- 一些 sql 子句没有简单的标准对应物(如子选择)
- 等等。
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.
当我想要类似于 sql 的查询(从用户中删除 status='blocked')时,我倾向于使用 HQL,当我不想使用字符串附加时,我倾向于使用标准。
Another advantage of HQL is that you can define all your queries before hand, and even externalise them to a file or so.
HQL 的另一个优点是您可以事先定义所有查询,甚至将它们外部化到一个文件左右。
回答by Varun Mehta
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.
HQL 和criteriaQuery 在性能方面存在差异,每次使用criteriaQuery 触发查询时,它都会为表名创建一个新别名,该别名不会反映在任何数据库的上次查询缓存中。这会导致编译生成的 SQL 的开销,需要更多的时间来执行。
Regarding fetching strategies [http://www.hibernate.org/315.html]
关于获取策略[http://www.hibernate.org/315.html]
- Criteria respects the laziness settings in your mappings and guarantees that what you want loaded is loaded. This means one Criteria query might result in several SQL immediate SELECT statements to fetch the subgraph with all non-lazy mapped associations and collections. If you want to change the "how" and even the "what", use setFetchMode() to enable or disable outer join fetching for a particular collection or association. Criteria queries also completely respect the fetching strategy (join vs select vs subselect).
- HQL respects the laziness settings in your mappings and guarantees that what you want loaded is loaded. This means one HQL query might result in several SQL immediate SELECT statements to fetch the subgraph with all non-lazy mapped associations and collections. If you want to change the "how" and even the "what", use LEFT JOIN FETCH to enable outer-join fetching for a particular collection or nullable many-to-one or one-to-one association, or JOIN FETCH to enable inner join fetching for a non-nullable many-to-one or one-to-one association. HQL queries do not respect any fetch="join" defined in the mapping document.
- Criteria 尊重映射中的惰性设置,并保证加载您想要加载的内容。这意味着一个 Criteria 查询可能会导致多个 SQL 立即 SELECT 语句来获取具有所有非延迟映射关联和集合的子图。如果要更改“方式”甚至“内容”,请使用 setFetchMode() 启用或禁用特定集合或关联的外连接获取。Criteria 查询也完全尊重获取策略(join vs select vs subselect)。
- HQL 尊重映射中的惰性设置,并保证加载您想要加载的内容。这意味着一个 HQL 查询可能会导致多个 SQL 立即 SELECT 语句来获取具有所有非延迟映射关联和集合的子图。如果您想更改“如何”甚至“内容”,请使用 LEFT JOIN FETCH 为特定集合或可为空的多对一或一对一关联启用外连接获取,或使用 JOIN FETCH 启用内连接获取不可为空的多对一或一对一关联。HQL 查询不遵守映射文档中定义的任何 fetch="join" 。
回答by Zafar
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 :))
对我来说,标准是一个非常容易理解和进行动态查询的工具。但到目前为止我说的缺陷是它加载了所有多对等关系,因为我们只有三种类型的 FetchModes,即选择、代理和默认,在所有这些情况下它加载多一(如果有帮助,可能我错了我出去:))
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.
Criteria 的第二个问题是它加载了完整的对象,即如果我只想加载员工的 EmpName,它不会提出这个,它会提出完整的 Employee 对象,我可以从中获取 EmpName 因为这个它真的很糟糕报告。因为 HQL 只是加载(没有加载关联/关系)你想要的东西,所以多次提高性能。
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.
Criteria 的一个特点是它可以保护您免受 SQL 注入的影响,因为它是动态查询生成的,而在 HQL 中,您的查询要么是固定的,要么是参数化的,因此不受 SQL 注入的影响。
Also if you write HQL in ur aspx.cs files, then you are tightly coupled with ur DAL.
此外,如果您在您的 aspx.cs 文件中编写 HQL,那么您将与您的 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.
总的来说,我的结论是,有些地方你不能没有 HQL 之类的报告,所以使用它们,否则 Criteria 更容易管理。
回答by Alex Miller
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.
条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。HQL 没有任何方法来指定必要的提示。
You can find some more info here:
您可以在此处找到更多信息:
回答by Timo Westk?mper
To use the best of both worlds, the expressivity and conciseness of HQL and the dynamic nature of Criteria consider using Querydsl.
为了充分利用 HQL 的表现力和简洁性以及 Criteria 的动态特性,请考虑使用Querydsl。
Querydsl supports JPA/Hibernate, JDO, SQL and Collections.
Querydsl 支持 JPA/Hibernate、JDO、SQL 和集合。
I am the maintainer of Querydsl, so this answer is biased.
我是 Querydsl 的维护者,所以这个答案是有偏见的。
回答by Bojan Kraut
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:
一开始我们主要在我们的应用程序中使用 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();
so in our case the returned records are maps of needed properties.
所以在我们的例子中,返回的记录是所需属性的映射。