hibernate/hibernate-orm · error · GenericJDBCException
Could not extract row count from CallableStatement
Error message
Could not extract row count from CallableStatement
What it means
Expectation.OutParameter verifies write outcomes by reading the affected-row count from a stored-procedure OUT parameter via CallableStatement.getInt(parameterIndex()) (prepare() registers it as Types.NUMERIC). If that getInt call throws SQLException - parameter not registered, wrong index, or non-numeric value - Hibernate logs the SQLException and wraps it in GenericJDBCException with this message instead of verifying the row count.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/jdbc/Expectation.java:227
/**
* Essentially identical to {@link RowCount} except that the row count
* is obtained via an output parameter of a {@linkplain CallableStatement
* stored procedure}.
* <p>
* Statement batching is disabled when {@code OutParameter} is used.
*
* @since 6.5
*/
class OutParameter implements Expectation {
@Override
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql) {
final int result;
try {
result = toCallableStatement( statement ).getInt( parameterIndex() );
}
catch ( SQLException sqle ) {
sqlExceptionHelper.logExceptions( sqle, "Could not extract row count from CallableStatement" );
throw new GenericJDBCException( "Could not extract row count from CallableStatement", sqle );
}
if ( batchPosition < 0 ) {
checkNonBatched( expectedRowCount(), result, sql );
}
else {
checkBatched( expectedRowCount(), result, batchPosition, sql );
}
}
@Override
public void validate(boolean callable) throws MappingException {
if ( !callable ) {
throw new MappingException( "Expectation.OutParameter operates exclusively on CallableStatements" );
}
}
@Override
public int getNumberOfParametersUsed() {View on GitHub (pinned to fad1729dce)
Solutions
- Make the row-count available as a NUMERIC out parameter at the index the expectation reads (typically the first parameter) and keep callable = true on the annotation
- Align the procedure signature with the custom SQL: {? = call proc(?, ?)} if the count is a return value, or {call proc(?, ?, ?)} with the count as an explicit out parameter
- Inspect the wrapped SQLException (cause) to see whether registration, index, or type conversion failed
Example fix
// before
@SQLInsert(sql = "{ call insert_person(?, ?, ?) }", callable = true) // no out parameter for row count
@Expectation(type = ExpectationType.OUT_PARAM)
class Person { }
// after
@SQLInsert(sql = "{ ? = call insert_person(?, ?, ?) }", callable = true) // returns affected row count
@Expectation(type = ExpectationType.OUT_PARAM)
class Person { } Defensive patterns
Strategy: try-catch
Try / catch
try {
session.flush();
} catch (org.hibernate.exception.GenericJDBCException e) {
if (e.getMessage() != null && e.getMessage().contains("CallableStatement")) {
// out parameter not registered / wrong index / non-numeric:
// check the stored procedure signature and parameterIndex of the expectation
}
throw e;
} Prevention
- Keep the row-count out parameter as the first parameter of callable SQL and register expectations accordingly
- Smoke-test every @Expectation(OUT_PARAM) entity against the real procedure in CI
- Ensure the procedure returns the affected-row count as a NUMERIC-compatible type
When it happens
Trigger: Custom SQL with @Expectation(type = ExpectationType.OUT_PARAM) (or a custom subclass of Expectation.OutParameter) where the callable statement has no NUMERIC out parameter at the expected index, e.g. the procedure does not return the row count, or the out parameter sits at a different position than parameterIndex() expects.
Common situations: Stored-procedure insert/update/delete where the count parameter was dropped or reordered during a proc refactor; mixing function-style {?=call...} with procedure-style {call...} signatures; drivers that require out parameters to be registered before input parameters.
Related errors
- Expectation.OutParameter operates exclusively on CallableSta
- Expectation.OutParameter operates exclusively on CallableSta
- JDBC driver does not support named parameters for setArray.
- PostgreSQL only supports REF_CURSOR parameters as the first
- PostgreSQL only supports accessing REF_CURSOR parameters by
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/3dc154802d2eda22.
Report an issue: GitHub.