Hibernate HQL createQuery

时间:2012-04-09 21:27:34

标签: hibernate nhibernate-caches

我正在尝试以旧方式转换执行SQL查询的旧应用程序,如下所示:

java.sql.Connection connection = ....
String queryStr="select acct from Person where acct in (select acct from Document where dbcreate_date > DATEADD(hh,-12, GETDATE())) and status not in ('A','P')";
...
...
java.sql.Statement statement = connection.createStatement(
                ResultSet.TYPE_SCROLL_INSENSITIVE,
                ResultSet.CONCUR_READ_ONLY);
        rs = statement.executeQuery(queryStr);

上述代码大约需要10毫秒。这包括获取数据库连接,创建语句和执行查询。

我现在正在使用Hibenate HQL并创建了一个这样的HQL查询:

Query query = session.createQuery("select p.acct   from Person p  where p.acct in (select  acct from Document d where create_date > :date and status not in ('A','P'))");

现在只是这个语句“session.createQuery(....)”花了大约105毫秒,这比以前提到的旧方式完成整个查询的时间长了大约10倍。

现在我不确定Hibernate查询缓存是如何工作的,但是如果我第二次运行这个相同的HQL语句,则需要大约5毫秒。

现在我的问题是为什么使用Hibernate HQL会发生这种行为?任何人都知道“session.createQuery(...)”方法内部会发生什么,第一次需要更长的时间,但第二次运行的时间要少得多? 我还注意到Hibernate在执行“query.list()”时都会对数据库执行SQL。

感谢。

2 个答案:

答案 0 :(得分:2)

尝试在Hibernate中使用本机查询来比较性能:

Query query = session.createSQLQuery("select acct from Person where acct in (select acct from Document where dbcreate_date > DATEADD(hh,-12, GETDATE())) and status not in ('A','P')");

关于表现:

你并没有真正与两个问题进行比较。

你的第一个例子,直接的JDBC查询只是一个简单的查询(简单的Statement)。另一方面,HQL 中有一个参数 - 因此它将转换为JDBC PreparedStatement,并且为此编译SQL以便在多次调用它时可以快速运行它,并传递不同的变量值。

如果多次执行,您可能会发现HQL查询的平均速度比简单的JDBC查询快。

如果你只执行一次,那么简单的JDBC版本可能会比HQL更快,因为HQL最初会被编译。

这里有关于Statement vs PreparedStatement的一些有趣信息:

http://oreilly.com/catalog/jorajdbc/chapter/ch19.html

  

声明与PreparedStatement

     

人们普遍认为使用PreparedStatement对象是   比使用Statement对象更快。毕竟,准备好的声明   必须只针对数据库验证其元数据一次,而a   声明必须每次都这样做。那怎么可能是其他方式呢?   嗯,事情的真相是它需要大约65次迭代   在执行总时间之前准备好的声明赶上了   一份声明。这对您的性能有影响   应用程序,以及探索这些问题是本节的全部内容   约。

     

当谈到哪个SQL语句对象在下面表现得更好   典型的用法,陈述或准备好的陈述,事实就是这样   Statement对象产生最佳性能。当你考虑如何   SQL语句通常用于应用程序 - 1或2,   可能每次交易10-20(很少) - 你意识到a   Statement对象将在比a更短的时间内执行它们   PreparedStatement对象。

答案 1 :(得分:1)

您可以使用session.createCriteria以避免解析HQL并构建SQL。

尽管如此,对于复杂的查询,只比在第一次打击时支付一些小的惩罚(尽管它不可​​能是~100ms),而不是构建复杂的createCriteria结构。

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html

相关问题