JPA 和 Hibernate - 标准与 JPQL 或 HQL

发布于 2024-07-07 22:13:52 字数 378 浏览 12 评论 0原文

使用标准 或 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

白首有我共你 2024-07-14 22:13:55

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

HQL can cause security concerns like SQL injection.

迷途知返 2024-07-14 22:13:55

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

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

例如,我构建了 spring-data-jpa-mongodb-expressions 使用 Criteria API(与 Spring Data QBE 的方式相同)。

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

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).

I think spring data query generations are using jpaql rather criteria which I don't understand why.

み零 2024-07-14 22:13:54

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.

带刺的爱情 2024-07-14 22:13:54

一开始我们在应用程序中主要使用 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();

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

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:

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.

雪落纷纷 2024-07-14 22:13:54

对我来说 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.

断念 2024-07-14 22:13:54

对我来说,Criteria 最大的优势是示例 API,您可以在其中传递一个对象,hibernate 将根据这些对象属性构建一个查询。

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

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

当我想要类似于 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:

  • 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.

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.

顾北清歌寒 2024-07-14 22:13:54

这篇文章很老了。 大多数答案讨论的是 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.

云淡风轻 2024-07-14 22:13:54

动态条件查询我们可以根据我们的输入构建查询。如果 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.

楠木可依 2024-07-14 22:13:54
  • HQL是对数据进行选择和非选择操作,但是Criteria只是对数据进行选择,我们不能使用Criteria进行非选择操作
  • HQL适合执行静态查询,而Criteria适合执行动态查询
  • HQL 不支持分页概念,但我们可以使用 Criteria 实现分页
  • 。 Criteria 的执行时间比 HQL 更长。
  • 使用 Criteria,我们可以安全地使用 SQL 注入,因为它是动态查询生成,但在 HQL 中,因为您的查询要么是固定的,要么是参数化的,没有安全的 SQL 注入。

来源

  • HQL is to perform both select and non-select operations on the data, but Criteria is only for selecting the data, we cannot perform non-select operations using criteria
  • HQL is suitable for executing Static Queries, where as Criteria is suitable for executing Dynamic Queries
  • HQL doesn’t support pagination concept, but we can achieve pagination with Criteria
  • Criteria used to take more time to execute then HQL
  • With Criteria we are safe with SQL Injection because of its dynamic query generation but in HQL as your queries are either fixed or parametrized, there is no safe from SQL Injection.

source

两相知 2024-07-14 22:13:54

我不想在这里踢死马,但重要的是要提到 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.

流年已逝 2024-07-14 22:13:54

我也更喜欢使用 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.

森林散布 2024-07-14 22:13:54

这里的大多数答案都是误导性的,并提到 Criteria QueriesHQL 慢,但实际上并非如此。

如果您深入研究并执行一些测试,您会发现标准查询的性能比常规 HQL 好得多。

而且,通过条件查询,您可以获得面向对象的控制,这是HQL所不具备的。

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

Most the answers here are misleading and mention that Criteria Queries are slower than HQL, 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.

追星践月 2024-07-14 22:13:54

还有另一种方法。 我最终基于 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!

很糊涂小朋友 2024-07-14 22:13:53

要充分利用 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.

笑咖 2024-07-14 22:13:53

Criteria Api 是 Hibernate 的优秀概念之一。 根据我的观点,这些是我们可以区分 HQLCriteria Api 的几点

  1. HQL 是对数据执行选择和非选择操作,但是Criteria仅用于选择数据,我们不能使用Criteria执行非选择操作。
  2. HQL适合执行静态查询,而Criteria适合执行动态查询
  3. HQL不支持分页概念,但我们可以通过Criteria实现分页。
  4. Criteria 过去比 HQL 需要更多的时间来执行。
  5. 使用 Criteria,我们可以安全地使用 SQL 注入,因为它是动态查询生成的,但在 HQL 中,由于您的查询要么是固定的,要么是参数化的,所以不存在 SQL 注入的安全性

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

  1. HQL is to perform both select and non-select operations on the data, but Criteria is only for selecting the data, we cannot perform non-select operations using criteria.
  2. HQL is suitable for executing Static Queries, where as Criteria is suitable for executing Dynamic Queries
  3. HQL doesn’t support pagination concept, but we can achieve pagination with Criteria.
  4. Criteria used to take more time to execute than HQL.
  5. With Criteria we are safe with SQL Injection because of its dynamic query generation but in HQL as your queries are either fixed or parametrized, there is no safe from SQL Injection
心凉怎暖 2024-07-14 22:13:53

条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。 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:

平定天下 2024-07-14 22:13:53

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.

一枫情书 2024-07-14 22:13:52

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

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

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

Criteria is an object-oriented API, while HQL means string concatenation. That means all of the benefits of object-orientedness apply:

  1. 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.
  2. 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
  3. 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.

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.

九厘米的零° 2024-07-14 22:13:52

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.

兰花执着 2024-07-14 22:13:52

当我不知道输入将用于哪些数据时,我通常使用 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.

风尘浪孓 2024-07-14 22:13:52

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

另一方面,我使用 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.

叫嚣ゝ 2024-07-14 22:13:52

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

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

  • Criteria 尊重您的映射中的惰性设置,并保证您想要加载的内容已加载。 这意味着一个 Criteria 查询可能会导致多个 SQL 立即 SELECT 语句来获取具有所有非惰性映射关联和集合的子图。 如果您想更改“方式”甚至“内容”,请使用 setFetchMode() 启用或禁用特定集合或关联的外连接获取。 标准查询也完全遵循获取策略(连接、选择、子选择)。
  • HQL 尊重映射中的惰性设置,并保证加载您想要加载的内容。 这意味着一个 HQL 查询可能会导致多个 SQL 立即 SELECT 语句来获取具有所有非惰性映射关联和集合的子图。 如果要更改“方式”甚至“内容”,请使用 LEFT JOIN FETCH 启用特定集合或可为空的多对一或一对一关联的外连接提取,或使用 JOIN FETCH 启用不可为空的多对一或一对一关联的内部联接获取。 HQL 查询不遵循映射文档中定义的任何 fetch="join"。

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]

  • 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文