Java编码最佳实践,用于重用部分查询进行计数

KLE*_*KLE 5 java implementation pagination hibernate

对于我来说,implementation-result-in-hibernate-getting-total-number-of-rows问题引发了另一个问题,关于一些实现问题:

现在你知道你必须重用部分HQL查询来计算,如何有效地重用?

两个HQL查询之间的差异是:

  1. 选择是count(?),而不是pojo或属性(或列表)
  2. 不应该发生提取,因此不应该连接某些表
  3. order by应该消失

还有其他差异吗?

您是否有编码最佳实践来有效地实现这种重用(关注点:努力,清晰度,性能)?

简单HQL查询的示例:

    select       a     from A a join fetch a.b b where a.id=66 order by a.name
    select count(a.id) from A a                  where a.id=66
Run Code Online (Sandbox Code Playgroud)

更新

我收到的答案是:

  • 使用Criteria(但我们主要使用HQL)
  • 操纵String查询(但是每个人都同意这看起来很复杂而且不是很安全)
  • 包装查询,依赖于数据库优化(但有一种感觉,这是不安全的)

我希望有人会沿着另一条路径提供选项,更多与String连接相关.
我们可以使用通用部件构建两个HQL查询吗?

Chs*_*y76 1

好问题。这是我过去所做的(很多事情你已经提到过):

  1. 检查是否存在 SELECT子句。
    1. 如果不是,请添加select count(*)
    2. 否则检查它是否有DISTINCT或聚合函数。如果您使用 ANTLR 来解析您的查询,则可以解决这些问题,但它非常复杂。你可能最好用 来包装整个事情select count(*) from ()
  2. 消除fetch all properties
  3. fetch如果您将 HQL 解析为字符串,请从联接中删除。如果您确实使用 ANTLR 解析查询,则可以left join完全删除;检查所有可能的参考文献是相当混乱的。
  4. 消除order by
  5. 根据您在 1.2 中所做的操作,您需要删除/调整group by/ having

上述内容自然适用于 HQL。对于条件查询,您可以做的事情非常有限,因为它不适合轻松操作。如果您在 Criteria 之上使用某种包装层,您最终将得到相当于 ANTLR 解析结果的(有限)子集,并且在这种情况下可以应用上述大部分内容。

由于您通常会保留当前页面的偏移量和总计数,因此我通常首先使用给定的限制/偏移量运行实际查询,并且仅在count(*)返回的结果数大于或等于限制且偏移量为零时才运行查询(在所有其他情况下,我要么运行count(*)之前,要么我已经得到所有结果)。当然,对于并发修改来说,这是一种乐观的方法。

更新(关于手工组装 HQL)

我不太喜欢这种方法。当映射为命名查询时,HQL 具有构建时错误检查的优势(从技术上讲,是运行时错误检查,因为必须构建 SessionFactory,尽管这通常是在集成测试期间完成的)。当在运行时生成时,它会在运行时失败:-) 进行性能优化也不是那么容易。

当然,同样的推理也适用于 Criteria,但由于定义明确的 API(而不是字符串连接),搞砸会更困难一些。并行构建两个 HQL 查询(分页查询和“全局计数”查询)也会导致代码重复(并且可能会出现更多错误),或者迫使您在顶部编写某种包装层来为您完成此操作。这两种方式都远非理想。如果您需要从客户端代码(如通过 API)执行此操作,问题会变得更糟。

对于这个问题,我其实也思考过不少Hibernate-Generic-DAO的搜索 API似乎是一个合理的妥协;我对上述链接问题的回答中有更多详细信息。