在多线程环境中,hibernate把hql转换为sql时,会频繁的调用classloader中的方法来加载class。在某些中间件中(例如tomcat),classloader在加载class时,是同步操作。这种组合大大降低了应用程序的性能。
相关文章
https://hibernate.atlassian.net/browse/HHH-10746
https://hibernate.atlassian.net/browse/HHH-4959
在hibernate 5.2.6版中,修改了这个问题,增加了配置
hibernate.query.conventional_java_constants
默认值为true,即在hql中不支持java常量的引用
例如:
from Table t where t.c_bh=com.xxx.Table.N_XXX
不会尝试解析“t.c_bh”,但是会尝试解析“com.xxx.Table.N_XXX”
之前版本的hibernate,在hql中碰到“xx.xx”时,都会调用classloader来尝试加载类,这个会导致classloader加载很多不存在的类(调用开销大),这是导致性能下降的原因。
堆栈1:
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:390)
- waiting to lock <0x00000007315a3870> (a org.eclipse.jetty.webapp.WebAppClassLoader)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:383)
at org.hibernate.util.ReflectHelper.classForName(ReflectHelper.java:95)
at org.hibernate.util.ReflectHelper.getConstantValue(ReflectHelper.java:122)
at org.hibernate.hql.ast.QueryTranslatorImpl$JavaConstantConverter.handleDotStructure(QueryTranslatorImpl.java:569)
at org.hibernate.hql.ast.QueryTranslatorImpl$JavaConstantConverter.visit(QueryTranslatorImpl.java:564)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:40)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:42)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:42)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:42)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
堆栈2:
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:171)
at org.hibernate.util.ReflectHelper.classForName(ReflectHelper.java:100)
at org.hibernate.util.ReflectHelper.getConstantValue(ReflectHelper.java:122)
at org.hibernate.hql.ast.QueryTranslatorImpl$JavaConstantConverter.handleDotStructure(QueryTranslatorImpl.java:569)
at org.hibernate.hql.ast.QueryTranslatorImpl$JavaConstantConverter.visit(QueryTranslatorImpl.java:564)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:40)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
at org.hibernate.hql.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:33)
at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:254)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)