hibernate/hibernate-orm · error · UnsupportedOperationException

Unwrap strategy not known for this Java type: " + getTypeNam

Error message

Unwrap strategy not known for this Java type: " + getTypeName()

What it means

The adaptor's unwrap() is intentionally unimplemented — a bare JavaType has no conversion semantics. Any code path reaching unwrap() on a JavaTypeBasicAdaptor (custom binders, converters, session operations) gets UnsupportedOperationException, signalling the mapping never supplied a JdbcType or converter to do the real work.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeBasicAdaptor.java:42

	public JavaTypeBasicAdaptor(Class<T> type, MutabilityPlan<T> mutabilityPlan) {
		super( type, mutabilityPlan );
	}

	@Override
	public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
		throw new JdbcTypeRecommendationException(
				"Could not determine recommended JdbcType for '" + getTypeName() + "'"
		);
	}

	@Override
	public boolean useObjectEqualsHashCode() {
		return true;
	}

	@Override
	public <X> X unwrap(T value, Class<X> type, WrapperOptions options) {
		throw new UnsupportedOperationException(
				"Unwrap strategy not known for this Java type: " + getTypeName()
		);
	}

	@Override
	public <X> T wrap(X value, WrapperOptions options) {
		throw new UnsupportedOperationException(
				"Wrap strategy not known for this Java type: " + getTypeName()
		);
	}

	@Override
	public String toString() {
		return "JavaTypeBasicAdaptor(" + getTypeName() + ")";
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Give the mapping a real JdbcType or AttributeConverter so unwrap() is never called on the adaptor
  2. Subclass AbstractClassJavaType and implement unwrap()/wrap() with real conversion
  3. Replace the bare registration with a full BasicType implementation

Example fix

// before
public class MoneyJavaType extends JavaTypeBasicAdaptor<Money> {
    public MoneyJavaType() { super(Money.class); }
    // unwrap inherited -> always throws
}

// after
public class MoneyJavaType extends AbstractClassJavaType<Money> {
    public MoneyJavaType() { super(Money.class); }
    @Override public <X> X unwrap(Money v, Class<X> t, WrapperOptions o) {
        if (t == String.class) return (X) v.toString();
        if (t == BigDecimal.class) return (X) v.amount();
        throw unknownUnwrap(t);
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean hasRealUnwrap(JavaType<?> jt) {
    return !(jt instanceof org.hibernate.type.descriptor.java.spi.JavaTypeBasicAdaptor);
}
// skip generic unwrap paths for adaptor-backed descriptors

Type guard

static boolean unwrapSafe(JavaType<?> javaType) {
    return !(javaType instanceof org.hibernate.type.descriptor.java.spi.JavaTypeBasicAdaptor);
}

Try / catch

try {
    X v = javaType.unwrap(value, target, options);
} catch (UnsupportedOperationException e) {
    // adaptor cannot convert: perform the conversion manually or fix the registration
    throw new IllegalStateException("type registration incomplete for "
        + javaType.getJavaTypeClass(), e);
}

Prevention

When it happens

Trigger: Binding or reading an attribute whose JavaType is only a registered adaptor, with no JdbcType/converter performing conversion; generic framework code calling unwrap() on arbitrary descriptors it discovers.

Common situations: Registrations that only flag a class as 'basic' without behavior; scaffolding types left in production mappings; integration code probing descriptors generically.

Related errors


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