Hibernate Query Timeout Configuration Missing Cross-Version Cancellation Guarantee
0 reputation · 28 Apr 2023, 13:34 UTC
0 reputation · 28 Apr 2023, 13:34 UTC
Hibernate Query.setTimeout() establishes a JDBC statement timeout, but the framework does not guarantee cancellation of the underlying query when the timeout expires. This behavior creates ambiguity for applications that rely on timely query termination, especially when pagination via setMaxResults and setFirstResult is involved. The timeout applies at the statement level, and Hibernate's session management does not automatically propagate cancellation to the JDBC driver, potentially leaving threads active after the timeout period. Furthermore, exception handling differs across Hibernate major versions: version 5 raises QueryTimeoutException directly, while version 6 may wrap the exception in PersistenceException or treat it as a runtime exception, affecting upstream error handling strategies. The interaction between pagination boundaries and timeout enforcement also raises questions about whether a timeout applied to a paginated query respects the configured page size or continues fetching beyond it.
Under what conditions does Hibernate.cancel() effectively terminate a timed-out query across supported versions? How should applications reconcile version-specific exception types when implementing cross-platform timeout logic? Does configuring setMaxResults in conjunction with setTimeout() guarantee that excess results are discarded once the timeout fires, or may the driver continue returning rows beyond the page boundary?
34775 reputation · 28 Apr 2023, 16:44 UTC
Hibernate does not guarantee that a timed-out query is cancelled across versions. Query.setTimeout() maps to java.sql.Statement.setQueryTimeout(), which asks the JDBC driver to bound the statement; the driver and database decide whether to stop execution. Hibernate 5 exposes Session.cancelQuery() in some builds, and Hibernate 6 API availability differs by artifact, but there is no cross-version Hibernate.cancel() method. Cancellation can work only if the live JDBC statement is still reachable, the driver implements cancellation, and the database kills the query while it is running. Invoking cancellation after the timeout exception has already thrown is usually too late.
Statement is still open and owned by the same session or thread.Statement.cancel() by signalling the database.Do not catch a single type. At the repository boundary, catch the JPA PersistenceException for your namespace (jakarta.persistence in Hibernate 6, javax.persistence in Hibernate 5), plus org.hibernate.query.QueryTimeoutException and org.hibernate.exception.JDBCException. Unwrap the cause chain for java.sql.SQLTimeoutException or driver-specific SQLState, then normalize to your own domain timeout exception. Treat the exact wrapping as version-artifact dependent; verify against your jars.
try {
query.setTimeout(seconds);
query.getResultList();
} catch (jakarta.persistence.PersistenceException | org.hibernate.query.QueryTimeoutException ex) {
Throwable cause = ex;
while (cause != null && !(cause instanceof java.sql.SQLTimeoutException)) {
cause = cause.getCause();
}
throw new DomainTimeoutException("Query timed out", cause);
}
No. setMaxResults() and setFirstResult() become SQL LIMIT/OFFSET only when the dialect supports pushdown; otherwise Hibernate may fetch and discard rows client-side. A statement timeout does not create an atomic page-boundary stop. The database may continue producing rows after the client stops reading, and client-side enforcement can return rows beyond the page boundary. Close the result set and statement promptly, but do not assume the database stops work at the page limit.
setTimeout, and setMaxResults; capture the full stack trace and SQLState.LIMIT/OFFSET is pushed to the database or applied by row discarding.For strict termination, use database-side pagination, keep the timeout low, isolate the query in a transaction or connection you can close, and rely on database-specific monitoring or cancellation rather than Hibernate alone.
Missing diagnostic detail: which exact Hibernate version, JPA namespace, and JDBC driver are you running? This determines whether Session.cancelQuery exists and which exception types to catch.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.