hibernate/hibernate-orm · error · UnsupportedOperationException

PostgreSQL only supports accessing REF_CURSOR parameters by

Error message

PostgreSQL only supports accessing REF_CURSOR parameters by position

What it means

PostgreSQL JDBC has no mechanism to resolve a refcursor by name, so PostgreSQLLegacyDialect.getResultSet(CallableStatement, String name) unconditionally throws UnsupportedOperationException. Hibernate reaches it when a REF_CURSOR output parameter is retrieved by name instead of position (for example ProcedureOutputs.getOutput(name).asResultSet()).

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java:1170

	}


	@Override
	public CallableStatementSupport getCallableStatementSupport() {
		return getVersion().isSameOrAfter( 11 ) ? PostgreSQLCallableStatementSupport.INSTANCE : PostgreSQLCallableStatementSupport.V10_INSTANCE;
	}

	@Override
	public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
		if ( position != 1 ) {
			throw new UnsupportedOperationException( "PostgreSQL only supports REF_CURSOR parameters as the first parameter" );
		}
		return (ResultSet) statement.getObject( 1 );
	}

	@Override
	public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
		throw new UnsupportedOperationException( "PostgreSQL only supports accessing REF_CURSOR parameters by position" );
	}

	@Override
	public boolean qualifyIndexName() {
		return false;
	}

	@Override
	public IdentityColumnSupport getIdentityColumnSupport() {
		return PostgreSQLIdentityColumnSupport.INSTANCE;
	}

	@Override
	public NationalizationSupport getNationalizationSupport() {
		return NationalizationSupport.IMPLICIT;
	}

	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Retrieve the cursor by position 1 instead of by name
  2. Switch to a set-returning function called via select
  3. Avoid REF_CURSOR parameters entirely on PostgreSQL

Example fix

// before
ProcedureOutputs outputs = procCall.getOutputs();
ResultSet rs = outputs.getOutput( "result_cursor" ).asResultSet(); // -> throws

// after
ResultSet rs = outputs.getOutputByPosition( 1 ).asResultSet();
Defensive patterns

Strategy: fallback

Validate before calling

// never address PostgreSQL REF_CURSOR outputs by name
if ( outputName != null && dialect instanceof PostgreSQLLegacyDialect ) {
    outputName = null; // use position 1 instead
}

Try / catch

try {
    return outputs.getOutput( name ).asResultSet();
}
catch ( UnsupportedOperationException e ) {
    // PostgreSQL has no by-name cursor access: fall back to positional retrieval
    return outputs.getOutputByPosition( 1 ).asResultSet();
}

Prevention

When it happens

Trigger: Named retrieval of a REF_CURSOR output parameter from a ProcedureCall/StoredProcedureQuery on PostgreSQL; frameworks that address stored-procedure outputs by parameter name.

Common situations: Code ported from Oracle where named-cursor access is idiomatic; migrations of legacy DAO layers that name every output parameter.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/18f18bc5f1528605. Report an issue: GitHub.