You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于createQuery偶发could not prepare statement异常的原因排查请求

间歇性出现"could not prepare statement"异常的排查思路

你遇到的是Hibernate执行createQuery时间歇性抛出could not prepare statement异常,底层根源是Connection is closed,只有10%的场景会触发,这个偶发问题确实挺棘手的,我来帮你梳理下可能的原因和排查方向:

问题代码

Session session = DB.getInstance().getSession(Id);
DesiredObject = (DesiredObject) session.createQuery( "from DesiredTable where Id = :id") .setParameter("id", Id).uniqueResult();

完整堆栈信息

Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:151)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:2104)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2034)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2012)
at org.hibernate.loader.Loader.doQuery(Loader.java:953)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2815)
at org.hibernate.loader.Loader.doList(Loader.java:2797)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2629)
at org.hibernate.loader.Loader.list(Loader.java:2624)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:396)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1396)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1558)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1526)
... 14 more
Caused by: java.sql.SQLException: Connection is closed
at com.zaxxer.hikari.pool.ProxyConnection$ClosedConnection.lambda$getClosedConnection$0(ProxyConnection.java:489)
at com.sun.proxy.$Proxy15.prepareStatement(Unknown Source)
at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:311)
at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:149)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:176)

可能的原因及排查方向

  • 连接池与数据库超时配置不匹配:从堆栈能看到用的是HikariCP,如果你的idleTimeout或maxLifetime配置过短,而数据库端的连接超时(比如MySQL的wait_timeout)比连接池设置的更长,就会出现连接池认为连接还可用,但数据库已经把闲置连接关掉的情况。只有当刚好拿到这种失效连接时,才会触发异常,所以是间歇性的。
  • Session管理逻辑有漏洞:你的DB.getInstance().getSession(Id)方法如果存在Session复用逻辑(比如同一个Id对应的Session被多次获取却没正确重置/关闭),可能导致Session持有的连接已经被归还到池或失效,后续用这个Session执行查询时就会拿到关闭的连接。
  • 连接泄漏问题:如果某些异常分支里漏掉了session.close()或者事务的commit/rollback()操作,会导致连接池里的连接被长期占用直到超时回收。当连接池可用连接不足时,可能会拿到刚被回收的失效连接,引发异常。
  • 连接池未开启连接有效性检测:如果HikariCP没有配置connectionTestQuery(比如select 1),连接池在分配连接前不会验证连接是否可用。当数据库因为负载、网络抖动主动关闭了部分空闲连接,连接池无法提前发现,就会出现偶发的连接关闭异常。
  • Session线程安全问题:Hibernate的Session本身不是线程安全的,如果getSession(Id)返回的Session被多个线程共享,可能出现一个线程关闭了连接,另一个线程还在使用这个连接执行查询的情况,从而抛出连接已关闭的异常。

内容的提问来源于stack exchange,提问作者dreambigcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:07:44