Java编码的最佳做法重复使用的一部分,查询数
-
05-07-2019 - |
题
的 执行-结果-呼-在休眠-得到-总数的-行 问题触发另一个问题对我来说,有关 一些执行情况的关注:
现在你知道你必须再利用的部分非常查询的做计数、如何重用有效?
两者之间的差异非常查询:
- 选择是
count(?)
, ,而不是只或财产(或列表的) - 的获取不应该发生,因此,一些表不应该加入
- 的
order by
应该消失
是否还有其他的差异?
你有没有 编码的最佳做法来实现这一重用有效 (关切的问题:努力、清晰度、性能)?
例如,为一个非常简单的查询:
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
更新
我收到答案:
- 使用 标准 (但是我们使用非常大多)
- 操纵字符串 查询(但每个人都同意这看起来复杂和不安全)
- 包装的查询, 依靠数据库的优化(但是有一种感觉,这是不安全)
我希望有人会得到选择另一条道路,更多的关于字符串连接。
我们可以建立两个非常查询使用共同的部分?
解决方案
好的问题。这是我做了什么,在过去的(许多事情你已经提到):
- 检查是否 选择 条款是存在的。
- 如果不是的话,请加
select count(*)
- 否则检查它是否有 不同的 或集合体的功能。如果你使用这些代码分析你的查询,这是可能的工作围绕这些,但这是相当参与。你很可能会更好,只是包装的整个事情
select count(*) from ()
.
- 如果不是的话,请加
- 删除
fetch all properties
- 删除
fetch
从加入如果你分析非常as string.如果你真的分析查询与这些代码,你可以除去left join
完全;这是相当混乱,以检查所有可能的参考文献。 - 删除
order by
- 根据你做了什么在1.2你会需要删除/调整
group by
/having
.
上述适用于非常、自然。对标准的查询,你很有限,与你可以做些什么,因为它不适合操纵容易。如果您使用的是某种形式的包层之上的条件,你会有同等的(有限)的子集这些代码分析结果和可适用上述大多数在这种情况。
因为你通常会举行,抵消当前页的总数,我通常运行实际查询与给予限制/抵消的第一和唯一运行的 count(*)
如果查询结果数量返回是多于或等于限制和偏移是零(在所有其他情况下我们运行的 count(*)
之前我已经得到了所有的结果无论如何)。这是一个乐观的方法方面的并行修改,课程。
更新 (手工装配非常)
我特别不喜欢这种做法。当映为名查询,非常具有优势的建立时的错误检查(良好,运行时间从技术上讲,因为它已经建成,尽管这通常是在一体化测试无论如何)。当在运行时生成的,它未能在运行时:-)做性能优化不是容易的。
同样的推理适用于标准,当然,但它是一个有点难搞砸了由于定义API相对于字符串连接。建立两个非常查询的并行(一页和"全球数"之一)也导致重复代码(而且可能更bug)或者迫使你写信有些种类的包装上的层顶到为你做它。这两种方法是远远不够理想。如果你需要做到这一点从客户代码(如在过API),该问题变得甚至更糟。
我实际上 思考一点 在这个问题。搜索API 休眠一般性道 似乎是一个合理的妥协;有更多的详细信息在我的回答上述联系的问题。
其他提示
你有没有尝试过让你意图明确的休眠通过设置一个投射在你的(SQL?)标准是什么?我大多已使用的标准,所以我不知道该如何适用于这是您的情况,但我已经被使用
getSession().createCriteria(persistentClass).
setProjection(Projections.rowCount()).uniqueResult()
让休眠图使用缓存/重复使用/智慧的东西本身..不真的知道有多少智慧的东西,它实际上,虽然..任何人都关心在评论这个吗?
嗯,我不知道这是一个最佳实践,但是我的实践:)
如果我有查询是这样的:
select A.f1,A.f2,A.f3 from A, B where A.f2=B.f2 order by A.f1, B.f3
我只是想知道有多少结果将得到我执行:
select count(*) from ( select A.f1, ... order by A.f1, B.f3 )
然后得到的结果作为一个整数,而不映射的结果,在一个组成。
分析你的查询,为删除的一些部分,如'了受'是非常复杂。一个良好的关系型数据库将优化您的查询对你。
好的问题。
在一个徒手非常情况我会用这样的事情,但这是不可重复使用,因为它是相当特定的实体
Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();
这样做一次调整的起始数,因此直到你网页通过。
对于标准虽然我用一样喜欢这个
final Criteria criteria = session.createCriteria(clazz);
List<Criterion> restrictions = factory.assemble(command.getFilter());
for (Criterion restriction : restrictions)
criteria.add(restriction);
criteria.add(Restrictions.conjunction());
if(this.projections != null)
criteria.setProjection(factory.loadProjections(this.projections));
criteria.addOrder(command.getDir().equals("ASC")?Order.asc(command.getSort()):Order.desc(command.getSort()));
ScrollableResults scrollable = criteria.scroll(ScrollMode.SCROLL_INSENSITIVE);
if(scrollable.last()){//returns true if there is a resultset
genericDTO.setTotalCount(scrollable.getRowNumber() + 1);
criteria.setFirstResult(command.getStart())
.setMaxResults(command.getLimit());
genericDTO.setLineItems(Collections.unmodifiableList(criteria.list()));
}
scrollable.close();
return genericDTO;
但是,这并的计算每一时间通过调用 ScrollableResults:last()
.