代码之家  ›  专栏  ›  技术社区  ›  cretzel

JPA和Hibernate-标准与JPQL或HQL

  •  283
  • cretzel  · 技术社区  · 17 年前

    使用的优点和缺点是什么 Criteria 或 HQL ?标准API是一种很好的面向对象的方式来表示Hibernate中的查询,但有时标准查询比HQL更难理解/构建。

    你什么时候使用标准,什么时候使用HQL?在哪些用例中您更喜欢什么?或者只是一个品味问题?

    21 回复  |  直到 8 年前
        1
  •  203
  •   cretzel    17 年前

    对于动态查询,我更喜欢标准查询。例如,根据某个参数动态添加某些排序或保留某些部分(例如限制)要容易得多。

    另一方面,我将hql用于静态和复杂查询,因为它更容易理解/读取hql。此外,我认为,HQL的功能更强大一些,例如,对于不同的连接类型。

        2
  •  89
  •   Varun Mehta    17 年前

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

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

    • 条件尊重映射中的惰性设置,并确保加载所需的内容。这意味着一个条件查询可能会导致多个SQL立即选择语句来获取具有所有非延迟映射关联和集合的子图。如果要更改“如何”甚至“什么”,请使用setFetchMode()为特定集合或关联启用或禁用外部联接提取。条件查询也完全遵守提取策略(联接与选择与子选择)。
    • HQL尊重映射中的惰性设置,并确保加载所需的内容。这意味着一个HQL查询可能会导致多个SQL立即选择语句来获取具有所有非延迟映射关联和集合的子图。如果要更改“如何”甚至“什么”,请使用Left Join Fetch为特定集合启用外部联接提取,或者使用可为空的多对一或一对一关联,或者使用Join Fetch为不可为空的多对一或一对一关联启用内部联接提取。HQL查询不遵守映射文档中定义的任何fetch=“join”。
        3
  •  38
  •   Craig Walker    17 年前

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

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

    因为hql非常类似于sql(大多数开发人员已经非常熟悉),所以这些“不必记住”参数的权重并没有那么大。如果HQL更不同,那么这将更重要。

        4
  •  34
  •   Arthur Thomas    17 年前

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

        5
  •  31
  •   Brian Deterling    17 年前

    HQL更容易阅读,使用EclipseHibernate插件等工具更容易调试,并且更容易记录。条件查询更适合于在运行时确定大量行为的情况下构建动态查询。如果您不了解SQL,我可以理解使用条件查询,但总的来说,如果我知道自己想要什么,我更喜欢HQL。

        6
  •  22
  •   Alex Miller    17 年前

    条件是指定利用二级查询缓存中的特殊优化进行自然键查找的唯一方法。HQL没有任何方法来指定必要的提示。

    您可以在这里找到更多信息:

        7
  •  20
  •   Arvind    11 年前

    标准API是Hibernate的一个好概念。根据我的观点,这是我们能区别 HQL 和 标准API

    1. HQL是对数据同时执行选择操作和非选择操作,但条件仅用于选择数据,不能使用条件执行非选择操作。
    2. hql适合执行静态查询,其中as标准适合执行动态查询。
    3. HQL不支持 分页 概念,但是我们可以用标准实现分页。
    4. 标准用于比HQL执行更多时间。
    5. 根据我们的安全标准 SQL注入 由于它的动态查询生成,但是在HQL中,由于查询是固定的或是参数化的,所以不能安全地进行SQL注入。
        8
  •  13
  •   Max Nanasy    12 年前

    对于我来说,标准是非常容易理解和进行动态查询的。但我到目前为止所说的缺陷是它加载了所有的一个ETC关系,因为我们只有三种类型的fetchmode,即select、proxy和default,在所有这些情况下,它加载了多个fetchmode(如果这样帮助我,可能是我错了:)

    标准的第二个问题是它加载完整的对象,也就是说,如果我只想加载一个雇员的empname,它就不会得到这个insted,它会得到完整的empname,因此我可以从中得到empname。 在报道方面真的很糟糕 . 因为hql只加载(不加载关联/关系)你想要的东西,所以会多次提高性能。

    标准的一个特点是,它可以保护u不受SQL注入的影响,因为它的动态查询生成与hql中的as-ur查询一样是固定的或是参数化的,所以不受SQL注入的影响。

    另外,如果您在URASPX.cs文件中编写HQL,那么您将与URDAL紧密耦合。

    总的来说,我的结论是,有些地方没有类似hql的报告,你就不能生活,所以使用它们,其他的标准更容易管理。

        9
  •  12
  •   Timo Westkämper    15 年前

    为了更好地利用两者,HQL的表达性和简洁性以及标准的动态特性考虑使用 Querydsl .

    querydsl支持jpa/hibernate、jdo、sql和collections。

    我是QueryDSL的维护者,所以这个答案是有偏见的。

        10
  •  11
  •   Miguel Ping    17 年前

    对我来说,最大的成功标准是示例API,在这里您可以传递一个对象,Hibernate将根据这些对象属性构建一个查询。

    除此之外,标准API也有其独特之处(我相信Hibernate团队正在改写API),比如:

    • criteria.createAalias(“obj”)强制内部联接而不是可能的外部联接
    • 不能两次创建同一别名
    • 一些SQL子句没有简单的条件对应项(如子select)
    • 等。

    当我需要类似于SQL的查询时,我倾向于使用HQL(从status='blocked'的用户中删除),当我不想使用字符串追加时,我倾向于使用条件。

    hql的另一个优点是,您可以在手工之前定义所有查询,甚至将它们外部化到一个文件中。

        11
  •  9
  •   user1165443    14 年前

    标准API提供了一个SQL或HQL都不提供的独特功能。也就是说,它允许对查询进行编译时检查。

        12
  •  9
  •   Vlad Mihalcea    8 年前

    当查询过滤器在运行时动态应用时,条件API更适合于动态生成的查询。因此,到 prevent SQL Injection attacks 在构建动态查询时,标准API是一个很好的选择。

    条件查询的表达能力较低,因此很容易导致非常复杂和效率低下 SQL generated query . 我曾经加入过一个大型企业应用程序,其中标准API是默认的查询方法,甚至没有广泛的代码审查可以克服不知道我们将要结束什么样的SQL查询的恐惧。

    jpql或hql更具表现力,并且更容易预测关联生成的SQL查询。与标准查询相比,查看HQL查询也要容易得多。

    大多数实体查询用例不需要动态的where子句,因此您可以使用jpql实现大多数查询,同时为动态查询保留条件。

    值得注意的是,如果需要修改实体,那么选择具有JPQL或标准API的实体是有意义的。否则,DTO投影的性能会更好。退房 this article for more info .

        13
  •  7
  •   Michael Schmidt Kishore    13 年前

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

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

        14
  •  7
  •   Premraj    9 年前
    • hql是对数据同时执行select和non-select操作,但是条件只是选择数据,我们不能使用条件执行non-select操作。
    • hql适合执行静态查询,其中as标准适合执行动态查询。
    • HQL不支持分页概念,但我们可以通过标准实现分页
    • 用于执行比HQL花费更多时间的条件
    • 有了条件,我们可以安全地使用SQL注入,因为它是动态查询生成的,但是在HQL中,由于您的查询是固定的或是参数化的,所以没有安全的SQL注入。

    source

        15
  •  5
  •   user1679378    13 年前

    对于动态的条件查询,我们可以根据输入构造查询。如果HQL查询是静态查询,那么一旦构造,我们就不能更改查询的结构。

        16
  •  4
  •   Eskir    10 年前

    我不想在这里一意孤行,但重要的是要指出,标准查询现在已被弃用。使用HQL。

        17
  •  1
  •   Punit Patel    13 年前

    我还喜欢动态查询的条件查询。但是对于删除查询,我更喜欢使用HQL,例如,如果删除父ID为'XYZ'的子表中的所有记录,则HQL很容易实现,但是对于条件API,首先必须启动n个删除查询,其中n是子表记录数。

        18
  •  0
  •   Community Mohan Dere    9 年前

    这里的大多数答案都是误导性的,并提到 Criteria Queries 比…慢 HQL 但事实并非如此。

    如果您深入研究并执行一些测试,您将看到 标准查询的性能比常规的HQL要好得多 .

    并与 标准查询 你得到 面向对象控件 哪个不在那里 HQL .

    有关详细信息,请阅读此答案 here .

        19
  •  0
  •   Wallace Peng    8 年前

    还有另一种方法。我最终创建了一个基于Hibernate原始语法的HQL解析器,所以它首先解析HQL,然后它可以动态地注入动态参数,或者自动为HQL查询添加一些常见的过滤器。很好用!

        20
  •  0
  •   Sunnyday    8 年前

    这个职位很老。大多数答案都是关于休眠标准,而不是JPA标准。JPA2.1增加了criteriadelete/criteriaupdate和entitygraph来控制要提取的内容。标准API是更好的,因为Java是面向对象的。这就是创建JPA的原因。在编译JPQL时,它将在转换为SQL之前转换为AST树(OO模型)。

        21
  •  -3
  •   Lance Roberts    13 年前

    HQL可引起 安全 像SQL注入这样的问题。