hibernate/hibernate-orm · error · UnsupportedOperationException

Unsupported JdbcType nested in struct:

Error message

Unsupported JdbcType nested in struct: 

What it means

XmlHelper.convertedBasicValueToString serializes a fixed set of JDBC type families: numerics, booleans, chars/text, enums, dates/times/timestamps, binary, UUID, duration, and arrays. Writing an XML/struct aggregate that contains a nested value of any other JDBC kind falls into the default branch and throws UnsupportedOperationException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java:954

						}
					}
					else {
						for ( int i = 0; i < length; i++ ) {
							final Object arrayElement = Array.get( value, i );
							if ( arrayElement == null ) {
								appender.append( NULL_TAG );
							}
							else {
								appender.append( START_TAG );
								convertedBasicValueToString( appender, arrayElement, options, elementJavaType, elementJdbcType );
								appender.append( END_TAG );
							}
						}
					}
				}
				break;
			default:
				throw new UnsupportedOperationException( "Unsupported JdbcType nested in struct: " + jdbcType );
		}
	}

	private static int getSelectableMapping(
			EmbeddableMappingType embeddableMappingType,
			String name) {
		final int selectableIndex = embeddableMappingType.getSelectableIndex( name );
		if ( selectableIndex == -1 ) {
			throw new IllegalArgumentException(
					String.format(
							"Could not find selectable [%s] in embeddable type [%s] for XML processing.",
							name,
							embeddableMappingType.getMappedJavaType().getJavaTypeClass().getName()
					)
			);
		}
		return selectableIndex;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Map the nested value as a plain String attribute and serialize it in application code.
  2. Move the exotic value out of the aggregate to its own column.
  3. Upgrade Hibernate and re-test: the supported set grows across versions.
  4. For custom JdbcTypes, contribute support upstream or pre-convert to a supported type.

Example fix

// before
@Embeddable
public class Doc {
    String title;
    @JdbcTypeCode(SqlTypes.JSON)
    Map<String, Object> meta;   // -> Unsupported JdbcType nested in struct
}
// after: store the nested JSON as a string inside the aggregate
@Embeddable
public class Doc {
    String title;
    String metaJson;            // serialize meta with Jackson yourself
}
Defensive patterns

Strategy: validation

Validate before calling

static final Set<Integer> NESTED_OK = Set.of(
    SqlTypes.VARCHAR, SqlTypes.CHAR, SqlTypes.INTEGER, SqlTypes.BIGINT,
    SqlTypes.DECIMAL, SqlTypes.DATE, SqlTypes.TIMESTAMP, SqlTypes.VARBINARY,
    SqlTypes.UUID, SqlTypes.ARRAY /* ... */);

static void assertNestedTypesSupported(EmbeddableMappingType t) {
    t.forEachSelectable((i, s) -> {
        if (!NESTED_OK.contains(s.getJdbcMapping().getJdbcType().getDefaultSqlTypeCode())) {
            throw new IllegalStateException("Unsupported nested JDBC type: " + s);
        }
    });
}

Try / catch

try {
    session.persist(person);
} catch (UnsupportedOperationException ex) {
    if (ex.getMessage() != null && ex.getMessage().startsWith("Unsupported JdbcType nested in struct")) {
        throw new DataMappingException("Aggregate nests an unsupported JDBC type", ex);
    }
    throw ex;
}

Prevention

When it happens

Trigger: Persisting an entity whose XML or struct aggregate embeddable contains a field of an unsupported nested JdbcType, e.g. @JdbcTypeCode(SqlTypes.JSON), a nested SQLXML field, a raw STRUCT, spatial geometry (SqlTypes.GEOMETRY), or a vector type.

Common situations: Composing document types (JSON inside XML), adding spatial or vector fields to existing aggregate embeddables, custom JdbcTypes not covered by the switch.

Related errors


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