hibernate/hibernate-orm · error · UnsupportedOperationException
UserType does not support reading CallableStatement paramete
Error message
UserType does not support reading CallableStatement parameter values: {} What it means
UserTypeJdbcTypeAdapter.ValueExtractorImpl.extract(CallableStatement, int, WrapperOptions) (UserTypeJdbcTypeAdapter.java:108-122) reads OUT parameters of stored procedures whose Hibernate type is a UserType. It delegates only when the user type implements org.hibernate.type.ProcedureParameterExtractionAware; otherwise it throws this UnsupportedOperationException, meaning OUT values of this custom type cannot be read.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJdbcTypeAdapter.java:121
@Override
public J extract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
final J extracted = userType.nullSafeGet( rs, paramIndex, options );
logExtracted( paramIndex, extracted );
return extracted;
}
@Override
public J extract(CallableStatement statement, int paramIndex, WrapperOptions options) throws SQLException {
if ( userType instanceof ProcedureParameterExtractionAware ) {
//noinspection unchecked
final J extracted = ( (ProcedureParameterExtractionAware<J>) userType )
.extract( statement, paramIndex, options.getSession() );
logExtracted( paramIndex, extracted );
return extracted;
}
throw new UnsupportedOperationException( "UserType does not support reading CallableStatement parameter values: " + userType );
}
@Override
public J extract(CallableStatement statement, String paramName, WrapperOptions options) throws SQLException {
if ( userType instanceof ProcedureParameterExtractionAware ) {
//noinspection unchecked
final J extracted = ( (ProcedureParameterExtractionAware<J>) userType )
.extract( statement, paramName, options.getSession() );
logExtracted( paramName, extracted );
return extracted;
}
throw new UnsupportedOperationException( "UserType does not support reading CallableStatement parameter values: " + userType );
}
private void logExtracted(int paramIndex, J extracted) {
if ( JdbcExtractingLogging.LOGGER.isTraceEnabled() ) {
if ( extracted == null ) {View on GitHub (pinned to fad1729dce)
Solutions
- Implement org.hibernate.type.ProcedureParameterExtractionAware<J> on the UserType and provide the positional extract(CallableStatement, int, SharedSessionContract) implementation that reads the underlying JDBC type and converts it.
- Change the stored procedure signature to return a basic type (String/numeric) and convert to your domain type in Java.
- Replace the UserType mapping with an AttributeConverter over a standard JDBC type, which supports procedure extraction natively.
Example fix
// before - plain UserType: reading OUT param fails
public class MoneyType implements UserType<Money> { ... }
Money m = query.getOutputParameterValue( 1 );
// after - extraction-aware user type
public class MoneyType implements UserType<Money>, ProcedureParameterExtractionAware<Money> {
@Override
public Money extract(CallableStatement statement, int index, SharedSessionContract session)
throws SQLException {
return Money.of( statement.getBigDecimal( index ) );
}
// ... existing UserType methods
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before declaring OUT params of a custom type on a stored procedure
if ( !( userType instanceof org.hibernate.type.ProcedureParameterExtractionAware<?> ) ) {
// change the OUT parameter to a basic type and convert in Java,
// or implement extraction on the UserType first
} Type guard
static boolean supportsProcedureExtraction(org.hibernate.usertype.UserType<?> userType) {
return userType instanceof org.hibernate.type.ProcedureParameterExtractionAware<?>;
} Try / catch
try {
query.execute();
@SuppressWarnings("unchecked")
Money m = (Money) query.getOutputParameterValue( 1 );
} catch ( UnsupportedOperationException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "CallableStatement parameter values" ) ) {
// re-register the OUT param as BigDecimal and convert manually
} else throw e;
} Prevention
- When introducing stored procedures over domain-specific types, extend the UserType with ProcedureParameterExtractionAware (both positional and named extract).
- Keep an integration test per stored procedure that exercises OUT-parameter retrieval.
- Consider AttributeConverter + basic JDBC types for procedure boundaries.
When it happens
Trigger: A StoredProcedureQuery declares an OUT/INOUT parameter typed with a UserType (registerStoredProcedureParameter(i, MyType.class ...) or @ProcedureParameter on a typed class) and you call execute()/getOutputParameterValue(i); extraction fails unless the UserType implements ProcedureParameterExtractionAware.extract(CallableStatement, int, SharedSessionContract).
Common situations: Domain-specific types (money, codes) reused as stored-procedure parameters; existing UserTypes left unchanged when stored procedures returning those types were introduced.
Related errors
- Using UserType for CallableStatement parameter binding not s
- GaussDB only supports REF_CURSOR parameters as the first par
- SingleStore does not support resultsets via stored procedure
- Unexpected error extracting REF_CURSOR parameter [{}]
- JDBC driver does not support named parameters for setArray.
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d3f11da97f7d35c4.
Report an issue: GitHub.