hibernate/hibernate-orm · error · UnsupportedOperationException

Using UserType for CallableStatement parameter binding not s

Error message

Using UserType for CallableStatement parameter binding not supported

What it means

ValueBinderImpl.bind(CallableStatement, J, String, WrapperOptions) (UserTypeJdbcTypeAdapter.java:178-184) is called when a UserType-mapped value must be bound to a stored-procedure parameter by NAME, and it throws unconditionally: the UserType contract only offers nullSafeSet(PreparedStatement, ...) with positional indexes, so named CallableStatement binding cannot be supported through this adapter.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJdbcTypeAdapter.java:182

			this.userType = userType;
		}

		@Override
		public void bind(PreparedStatement st, J value, int index, WrapperOptions options) throws SQLException {
			if ( JdbcBindingLogging.LOGGER.isTraceEnabled() ) {
				if ( value == null ) {
					JdbcBindingLogging.logNullBinding( index, userType.getSqlType() );
				}
				else {
					JdbcBindingLogging.logBinding( index, userType.getSqlType(), value );
				}
			}
			userType.nullSafeSet( st, value, index, options );
		}

		@Override
		public void bind(CallableStatement st, J value, String name, WrapperOptions options) {
			throw new UnsupportedOperationException( "Using UserType for CallableStatement parameter binding not supported" );
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Register and bind the parameter positionally: setParameter(1, value) - the positional bind path (bind with index) delegates to UserType.nullSafeSet and works.
  2. Replace the UserType mapping with an AttributeConverter over a standard JDBC type or a proper JdbcType implementation that implements ProcedureParameterNamedBinder, which does support named binding.
  3. If the value can be represented as a basic type for the call, unwrap/convert it before setParameter.

Example fix

// before - named bind on a UserType parameter -> UnsupportedOperationException
StoredProcedureQuery q = em.createStoredProcedureQuery("calc");
q.registerStoredProcedureParameter("amount", Money.class, ParameterMode.IN);
q.setParameter("amount", money);

// after - positional registration/binding uses UserType.nullSafeSet
StoredProcedureQuery q = em.createStoredProcedureQuery("calc");
q.registerStoredProcedureParameter(1, Money.class, ParameterMode.IN);
q.setParameter(1, money);
Defensive patterns

Strategy: validation

Validate before calling

// Use positional style whenever a UserType-typed parameter is involved
StoredProcedureQuery q = em.createStoredProcedureQuery("calc");
q.registerStoredProcedureParameter(1, Money.class, ParameterMode.IN);
q.setParameter(1, money); // positional bind delegates to UserType.nullSafeSet
// rule: never setParameter("name", value) for UserType-mapped parameters

Type guard

static boolean isUserTypeMapped(org.hibernate.type.BasicType<?> t) {
    return t instanceof org.hibernate.type.internal.UserTypeSqlTypeAdapter
        || t instanceof org.hibernate.type.internal.UserTypeJdbcTypeAdapterMarker;
}

Prevention

When it happens

Trigger: A StoredProcedureQuery parameter registered with a UserType (e.g. registerStoredProcedureParameter("p", MyType.class, ParameterMode.IN)) and bound via setParameter("p", value): Hibernate routes the named bind to bind(CallableStatement, value, name, options) and gets this UnsupportedOperationException.

Common situations: Migrating positional stored-procedure calls to named-parameter style while using custom UserTypes; procedures whose signatures require named binding on drivers/oracle-style call syntax; reusing types that worked fine for ordinary entity persistence.

Related errors


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