在使用Hibernate开发的过程中,遇到场景in条件查询,查询条件里的个数超过1w甚至更高(且不讨论这种方式是否合理),在生成hql,执行查询的时候发现执行list()方法的时候特别慢。后经从网查询资料,得知:
Hibernate首先是使用了自己的数据库操作语言-HQL
Hibernate解析HQL的编译分析器用的是ANTLR分析器
HQL虽然是一种数据库操作语言,它只是方便编写和使用,本质上还是要转换成SQL语言来在数据库上执行的。
Hibernate在转换时主要用到了ANTLR,ANTLR是JAVA编写的词法分析器和语法分析器,功能很强大。
ANTLR将HQL转化成SQL语句,再实际执行SQL语句。
ANTLR所对应的文件名的格式是*.g的格式,Hibernate的jar包中含有3个语法定义文件。
Hibernate包含了3个语法定义文件:
1. hql.g定义了词法分析和语法分析,将hql解释成hql的抽象语法树(AST) 。
2. hql-sql.g将hql AST转化为sql AST,将生成模块与hibernate解耦。
3. sql -gen.g 从sql AST生成sql 语言。
详细可以查看Hibernate中的createQuery()的调用过程
通过QueryPlanCache的getHQLQueryPlan()方法获得查询计划HQLQueryPlan的一个实例,而后者主要是调用了 QueryTranslator的compile方法,编译HQL语句。在QueryTranslator的继承类 QueryTranslatorImpl的doCompile观察这个过程:
PHASE 1 : Parse the HQL into an AST.
PHASE 2 : Analyze the HQL AST, and produce an SQL AST.
PHASE 3 : Generate the SQL.
然后定位Debug发现在执行QueryTansalatorImpl类中的doCompile方法时消耗时间太长:
原来hql语句太长,ANTLR对hql进行编译成sql的过程中就要消耗很长的时间。之后我们通过使用hbernate中的Criteria条件查询来实现了查询,效率明显提高了上来。
criteria是hibernate特有的查询的方法,是面向对象的一种查询,可以让没有sql基础的开发者也能够准确的使用hibernate来操作数据库。
HQL是在java语言层面之外的另一种数据查询语言,和SQL极其接近,通用性强,便于SQL经验者使用,需要语法解析。考虑移植性时使用。 Criteria API是在java语言内的接口,不需要语法解析,直接操作底层对象,写出查询代码没有通用性。性能最大优化时使用。
另,通过原生sql方式也可以提高效率。