jpa和hibernate-criteria与jpql或hql的比较

zyfwsgd6  于 2021-07-03  发布在  Java
关注(0)|答案(14)|浏览(421)

使用criteria或hql的优缺点是什么?criteriaapi是在hibernate中表示查询的一种很好的面向对象的方法,但是有时criteria查询比hql更难理解/构建。
什么时候使用标准,什么时候使用hql?在哪些用例中您更喜欢什么?还是只是品味的问题?

n3schb8v

n3schb8v1#

hql和criteriaquery在性能方面存在差异,每次使用criteriaquery启动查询时,它都会为表名创建一个新的别名,该别名不会反映在任何数据库的上次查询缓存中。这会导致编译生成的sql的开销,需要更多的时间来执行。
关于抓取策略[http://www.hibernate.org/315.html]
条件尊重Map中的惰性设置,并保证加载所需的内容。这意味着一个条件查询可能会导致多个sql immediate select语句来获取具有所有非延迟Map关联和集合的子图。如果要更改“如何”甚至“什么”,请使用setfetchmode()为特定集合或关联启用或禁用外部联接获取。条件查询也完全遵循获取策略(join vs select vs subselect)。
hql尊重Map中的惰性设置,并保证加载您想要加载的内容。这意味着一个hql查询可能会导致几个sql immediate select语句来获取具有所有非延迟Map关联和集合的子图。如果要更改“如何”甚至“什么”,请使用left join fetch为特定集合或可为null的多对一或一对一关联启用外部联接获取,或使用join fetch为不可为null的多对一或一对一关联启用内部联接获取。hql查询不尊重Map文档中定义的fetch=“join”。

jjjwad0x

jjjwad0x2#

对我来说,标准是一个很容易理解和动态查询。但到目前为止,我说的缺陷是它加载了所有多个one etc关系,因为我们只有三种类型的fetchmode,即select、proxy和default,在所有这些情况下,它加载了多个one(如果这样的话,可能我错了,请帮我一把:)
标准的第二个问题是,它加载完整的对象,即如果我只想加载一个雇员的empname,它不会出现这个,而它会出现完整的雇员对象,我可以从它得到empname,因为它在报告中真的很糟糕。其中hql只是加载(没有加载关联/关系)你想要的,所以性能提高了很多倍。
criteria的一个特性是,它可以保护u不受sql注入的影响,因为它可以动态生成查询,而在hql中,由于ur查询是固定的或参数化的,所以不受sql注入的影响。
另外,如果您在uraspx.cs文件中编写hql,那么您将与urdal紧密耦合。
总的来说,我的结论是,有些地方没有类似hql的报告是无法生存的,所以使用其他标准更容易管理。

jjhzyzn0

jjhzyzn03#

为了充分利用这两个方面的优点,hql的表达性和简洁性以及标准的动态特性都考虑使用querydsl。
querydsl支持jpa/hibernate、jdo、sql和collections。
我是querydsl的维护者,所以这个答案是有偏见的。

slmsl1lt

slmsl1lt4#

criteriaapi提供了sql和hql都不提供的一个独特特性。它允许对查询进行编译时检查。

fcy6dtqo

fcy6dtqo5#

criteria是一个面向对象的api,而hql意味着字符串连接。这意味着面向对象的所有好处都适用于:
在其他条件相同的情况下,oo版本不太容易出错。任何旧字符串都可以附加到hql查询中,而只有有效的criteria对象才能将其添加到criteria树中。实际上,条件类受到更多的约束。
有了auto-complete,oo更容易发现(至少对我来说,这样更容易使用)。您不一定需要记住查询的哪些部分去了哪里;ide可以帮助您
你也不需要记住语法的细节(比如哪些符号在哪里)。您需要知道的只是如何调用方法和创建对象。
由于hql与sql非常相似(大多数开发人员已经非常了解sql),因此这些“不必记住”参数没有那么重要。如果hql更不同,那么这将更重要。

ojsjcaue

ojsjcaue6#

条件是指定利用二级查询缓存中的特殊优化的自然密钥查找的唯一方法。hql没有任何方法来指定必要的提示。
您可以在此处找到更多信息:
http://tech.puredanger.com/2009/07/10/hibernate-query-cache/

bn31dyow

bn31dyow7#

hql将对数据执行选择和非选择操作,但条件仅用于选择数据,我们不能使用条件执行非选择操作
hql适合于执行静态查询,而as条件适合于执行动态查询
hql不支持分页的概念,但是我们可以用标准实现分页
用于比hql花费更多时间执行的条件
与criter

fhity93d

fhity93d8#

hql更易于阅读,更易于使用eclipse hibernate插件等工具进行调试,更易于记录。条件查询更适合于在运行时确定许多行为的情况下构建动态查询。如果你不懂sql,我可以理解使用criteria查询,但总的来说,如果我知道我想要什么,我更喜欢hql。

ijnw1ujt

ijnw1ujt9#

我更喜欢动态查询的条件查询。例如,根据某些参数,动态添加一些排序或保留某些部分(例如限制)要容易得多。
另一方面,我将hql用于静态和复杂的查询,因为它更容易理解/读取hql。另外,我认为hql更强大一些,例如,对于不同的连接类型。

rbpvctlc

rbpvctlc10#

criteriaapi是hibernate的一个好概念。根据我的观点,这些是我们能够区分hql和criteriaapi的几个要点
hql将对数据执行选择和非选择操作,但条件仅用于选择数据,我们不能使用条件执行非选择操作。
hql适合于执行静态查询,而as条件适合于执行动态查询
hql不支持分页的概念,但是我们可以用标准实现分页。
用于比hql花费更多时间执行的条件。
有了条件,sql注入是安全的,因为它可以动态生成查询,但在hql中,由于查询是固定的或参数化的,sql注入是不安全的

ffx8fchx

ffx8fchx11#

当我不知道在哪些数据块上使用什么输入时,我通常使用标准。比如在一个搜索表单上,用户可以输入1到50个项目中的任何一个,我不知道他们会搜索什么。当我检查用户正在搜索的内容时,很容易将更多内容附加到条件中。我认为在这种情况下放置hql查询会有点麻烦。hql是伟大的,虽然当我知道我到底想要什么。

p4tfgftt

p4tfgftt12#

标准api

criteriaapi更适合于动态生成的查询。因此,如果您想添加where子句筛选器、join子句或更改order by子句或投影列,那么criteriaapi可以帮助您以一种还可以防止sql注入攻击的方式动态生成查询。
另一方面,criteria查询的表达能力较差,甚至会导致非常复杂和低效的sql查询。

jpql和hql

jpql是jpa标准的实体查询语言,而hql扩展了jpql并添加了一些特定于hibernate的特性。
jpql和hql非常有表现力,类似于sql。与criteriaapi不同,jpql和hql可以很容易地预测jpa提供者生成的底层sql查询。检查hql查询也比标准查询容易得多。
值得注意的是,如果需要修改实体,那么选择带有jpql或criteriaapi的实体是有意义的。否则,dto投影是更好的选择。

结论

如果不需要改变实体查询结构,那么可以使用jpql或hql。如果需要更改筛选或排序条件或更改投影,请使用条件api。
然而,仅仅因为您使用的是jpa或hibernate,并不意味着您不应该使用原生sql。sql查询非常有用,jpql和criteriaapi不能代替sql。

y0u0uwnf

y0u0uwnf13#

对我来说,标准的最大优势是示例api,在这里您可以传递一个对象,hibernate将基于这些对象属性构建一个查询。
除此之外,criteria api也有其独特之处(我相信hibernate团队正在重新设计api),比如:
criterias.createalias(“obj”)强制内部联接,而不是可能的外部联接
不能两次创建同一别名
一些sql子句没有简单的条件对应项(如subselect)
等。
当我想要类似于sql的查询(delete from users where status='blocked')时,我倾向于使用hql,当我不想使用字符串追加时,我倾向于使用criteria。
hql的另一个优点是,您可以预先定义所有查询,甚至可以将它们外部化到一个文件中。

7vhp5slm

7vhp5slm14#

我们最初在应用程序中主要使用标准,但后来由于性能问题被hql取代。
我们主要使用非常复杂的查询和多个连接,这会导致在条件中出现多个查询,但在hql中非常优化。
在这种情况下,我们只在特定对象上使用几个属性,而不是完整对象。对于条件,问题还在于字符串连接。
假设您需要在hql中显示用户的名字和姓氏,这非常简单 (name || ' ' || surname) 但在克里特利亚这是不可能的。
为了克服这一点,我们使用了resulttransformer,其中有一些方法实现了这种连接以获得所需的结果。
今天我们主要使用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();

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

相关问题