1. 程式人生 > >Hibernate HQL的條件中如果in包含太多的引數會導致堆疊溢位StackOverflowError、org.hibernate.hql.ast.util.NodeTraverser.visit

Hibernate HQL的條件中如果in包含太多的引數會導致堆疊溢位StackOverflowError、org.hibernate.hql.ast.util.NodeTraverser.visit

轉自:http://www.bitiliu.com/archives/43

異常情況

java.lang.StackOverflowError
        at rg.hibernate.hql.ast.QueryTranslatorImpl$JavaConstantConverter.visit(QueryTranslatorImpl.java:573)
        at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:64)
        at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:66)
        at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:66)
        at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:66)
        at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:66)


不論是使用 where x in(:x) 還是使用 where x in (1,2,3…)的方式,如果引用的引數超過堆疊空間,都會引發堆疊溢位異常。在大多數的JVM中,引數限制在9000~10000之間。

堆疊溢位的原因在於org.hibernate.hql.ast.util.NodeTraverser在解析語法樹的時候採用了遞迴演算法,大量的in引數會生成一個的子樹,子樹的深度和in引數的個數相同。解決方法是使用迭代的方式代替遞迴樹,這樣就不會耗盡堆疊。在Hibernate 3.2.x以上版本已經解決了這個問題。