使用Criteria或HQL的优缺点是什么?Criteria API 是在 Hibernate 中表达查询的一种很好的面向对象的方式,但有时 Criteria Queries 比 HQL 更难理解/构建。
您什么时候使用 Criteria,什么时候使用 HQL?在哪些用例中你更喜欢什么?还是只是口味问题?
使用Criteria或HQL的优缺点是什么?Criteria API 是在 Hibernate 中表达查询的一种很好的面向对象的方式,但有时 Criteria Queries 比 HQL 更难理解/构建。
您什么时候使用 Criteria,什么时候使用 HQL?在哪些用例中你更喜欢什么?还是只是口味问题?
我最喜欢动态查询的条件查询。例如,根据某些参数动态添加一些排序或保留一些部分(例如限制)要容易得多。
另一方面,我将 HQL 用于静态和复杂查询,因为它更容易理解/阅读 HQL。此外,我认为 HQL 更强大一些,例如对于不同的连接类型。
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"。
Criteria 是面向对象的 API,而 HQL 表示字符串连接。这意味着面向对象的所有好处都适用:
由于 HQL 非常类似于 SQL(大多数开发人员已经非常了解),因此这些“不必记住”的论点就没有那么重要了。如果 HQL 更不同,那么这将更重要。
当我不知道哪些输入将用于哪些数据时,我通常使用 Criteria。就像在用户可以输入 1 到 50 个项目中的任何一个的搜索表单上一样,我不知道他们将要搜索什么。当我检查用户正在搜索的内容时,很容易将更多内容附加到标准中。我认为在这种情况下放置 HQL 查询会有点麻烦。当我确切地知道我想要什么时,HQL 很棒。
HQL 更易于阅读,更易于使用 Eclipse Hibernate 插件等工具进行调试,并且更易于记录。标准查询更适合构建动态查询,其中很多行为是在运行时确定的。如果你不懂 SQL,我可以理解使用 Criteria 查询,但总的来说,如果我知道我想要什么,我更喜欢 HQL。
条件是指定利用二级查询缓存中的特殊优化的自然键查找的唯一方法。HQL 没有任何方法来指定必要的提示。
您可以在此处找到更多信息:
Criteria Api 是 Hibernate 的优秀概念之一。根据我的观点,这些是我们可以在HQL和Criteria Api之间有所不同的几点
Criteria API 更适合动态生成的查询。因此,如果您想添加 WHERE 子句过滤器、JOIN 子句或改变 ORDER BY 子句或投影列,那么 Criteria API 可以帮助您以一种同时防止 SQL 注入攻击的方式动态生成查询。
另一方面,Criteria 查询的表达能力较差,甚至会导致非常复杂和低效的 SQL 查询。
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。
要使用两全其美,HQL 的表现力和简洁性以及 Criteria 的动态特性考虑使用Querydsl。
Querydsl 支持 JPA/Hibernate、JDO、SQL 和集合。
我是Querydsl的维护者,所以这个答案是有偏见的。
对我来说,Criteria 是一个很容易理解和进行动态查询的方法。但到目前为止我说的缺陷是它加载了所有多一等关系,因为我们只有三种类型的 FetchMode,即选择、代理和默认,并且在所有这些情况下它加载多一(如果有帮助,我可能错了我出去:))
Criteria 的第二个问题是它加载了完整的对象,即如果我只想加载员工的 EmpName,它不会想出这个 insted 它会提供完整的 Employee 对象,因此我可以从中获取 EmpName,因为它真的很糟糕报告。HQL 只是加载(没有加载关联/关系)你想要的东西,所以性能会提高很多倍。
Criteria 的一个特点是它可以保护你免受 SQL 注入的影响,因为它的动态查询生成方式与在 HQL 中一样,因为你的查询要么是固定的,要么是参数化的,因此对 SQL 注入不安全。
此外,如果您在您的 aspx.cs 文件中编写 HQL,那么您将与您的 DAL 紧密耦合。
总的来说,我的结论是,有些地方没有 HQL 之类的报告就无法生存,因此请使用它们,否则标准更易于管理。
对我来说,Criteria 的最大胜利是 Example API,您可以在其中传递一个对象,hibernate 将基于这些对象属性构建一个查询。
除此之外,标准 API 有其怪癖(我相信 hibernate 团队正在重新设计 api),例如:
当我想要类似于 sql 的查询(从用户中删除 status='blocked')时,我倾向于使用 HQL,而当我不想使用字符串附加时,我倾向于使用条件。
HQL 的另一个优点是您可以预先定义所有查询,甚至可以将它们外部化到一个文件左右。
我们一开始在我们的应用程序中主要使用 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();
所以在我们的例子中,返回的记录是所需属性的映射。
Criteria api 提供了 SQL 或 HQL 都没有提供的一项独特功能。IE。它允许对查询进行编译时检查。
动态的条件查询我们可以根据我们的输入构造查询。如果 Hql 查询是静态查询,一旦我们构造我们就不能改变查询的结构。
我不想在这里踢死马,但重要的是要提到现在不推荐使用 Criteria 查询。使用 HQL。
对于动态查询,我也更喜欢 Criteria Queries。但是我更喜欢使用 hql 进行删除查询,例如,如果从子表中删除父 id 'xyz' 的所有记录,这很容易通过 HQL 实现,但是对于标准 API,我们必须首先触发 n 个删除查询,其中 n 是子表的数量表记录。
这里的大多数答案都具有误导性,并提到Criteria Queries
比 慢HQL
,实际上并非如此。
如果您深入研究并执行一些测试,您会发现Criteria Queries 比常规 HQL 执行得更好。
此外,使用Criteria Query您可以获得HQL所没有的面向对象控制。
有关更多信息,请在此处阅读此答案。
还有另一种方法。我最终创建了一个基于 hibernate 原始语法的 HQL 解析器,因此它首先解析 HQL,然后它可以动态注入动态参数或为 HQL 查询自动添加一些常用过滤器。效果很好!
这个帖子很老了。大多数答案都是关于 Hibernate 标准,而不是 JPA 标准。JPA 2.1 添加了 CriteriaDelete/CriteriaUpdate 和 EntityGraph 来控制要获取的确切内容。Criteria API 更好,因为 Java 是 OO。这就是创建 JPA 的原因。JPQL 在编译时会先翻译成 AST 树(OO 模型),然后再翻译成 SQL。
另一点是,我认为 Criteria 更适合在它之上构建,而不是在最终代码中单独使用。
它比使用 jpql 或 hql 更适合使用它来构建库。
例如,我使用 Criteria API 构建了 spring-data-jpa-mongodb-expressions(与 spring data QBE 一样)。
我认为 spring 数据查询生成使用 jpaql 而不是我不明白为什么的标准。
HQL 可能会导致SQL 注入等安全问题。