Files
hibernate-demo/docs/output/procedure-hsqldb-jdbc-driver-quirk.txt
T

57 lines
3.1 KiB
Plaintext
Executable File

=== Raw JDBC probe (no Hibernate), HSQLDB 2.7.3, DYNAMIC RESULT SETS procedure ===
--- CallableStatement.execute() then getUpdateCount()/getResultSet() ---
execute() returned=false
getUpdateCount=0
getResultSet() = org.hsqldb.jdbc.JDBCResultSet@5649fd9b
row: 1 Alice 50000.00
row: 2 Bob 60000.00
getMoreResults=false
--- Statement.execute("CALL ...") vs CallableStatement.executeQuery() ---
--- via plain Statement.execute(CALL ...) ---
Statement.execute returned=false
getResultSet=null
--- via CallableStatement.executeQuery() ---
executeQuery ok, rs=org.hsqldb.jdbc.JDBCResultSet@5649fd9b
row via executeQuery: 1
row via executeQuery: 2
--- metadata: getMetaData() on CallableStatement before execute ---
getMetaData()=null
CONCLUSION: CallableStatement.execute() returns false (per JDBC spec this should mean
'no ResultSet, check update count'), and getUpdateCount() also returns 0 (not -1).
Yet CallableStatement.getResultSet() DOES return a live, iterable ResultSet with the
cursor's rows, and CallableStatement.executeQuery() works correctly end-to-end.
Statement.execute("CALL ...") is worse: execute()=false AND getResultSet()=null (the
result set is only reachable through the CallableStatement form).
Hibernate 7.4.5's ProcedureCallImpl (org.hibernate.procedure.internal.ProcedureCallImpl
/ StandardCallableStatementSupport) drives the call via execute() and trusts its boolean
to decide whether to attach a ResultSetOutput. Since HSQLDB's driver misreports that
boolean, getResultList() on a DYNAMIC RESULT SETS procedure fails with:
java.lang.IllegalStateException: Current CallableStatement was not a ResultSet, but getResultList was called
This reproduces identically through @NamedStoredProcedureQuery(resultClasses=...) and
through createStoredProcedureQuery(name, sqlResultSetMappingName) -- see
StoredProcedureHappyPathTest#resultSetProcedure_mappedToEntity_hitsHsqldbDriverIncompatibility
and #resultSetProcedure_mappedToDto_alsoHitsHsqldbDriverIncompatibility.
=== OUT parameter vs result-set consumption ORDER (raw JDBC, procedure with BOTH) ===
Procedure: combo(IN emp_id, OUT tax_amount) READS SQL DATA DYNAMIC RESULT SETS 1, opens a cursor
AND sets the OUT parameter.
Reading the OUT parameter BEFORE consuming the ResultSet:
execute()=false
OUT tax_amount = 7500.00 <- succeeds, no exception
(then) getResultSet() still returns the cursor with its rows intact
(then) OUT tax_amount read AGAIN = 7500.00 <- still succeeds
Reading the OUT parameter AFTER fully consuming the ResultSet:
rows consumed first
OUT tax_amount = 9000.00 <- also succeeds
CONCLUSION: unlike some JDBC drivers (historically SQL Server's, and some Oracle configurations)
that require a stored procedure's result set(s) to be fully consumed before OUT parameters
become readable, HSQLDB 2.7.3's driver imposes NO such ordering constraint. Reading the OUT
value before, interleaved with, or after draining the cursor all work identically. The
"ordering trap" described in stored-procedure folklore is real on SOME databases/drivers but
is NOT reproducible on HSQLDB -- worth stating explicitly rather than assuming it's universal.