hibernate/hibernate-orm · error · TransformationException

Error transforming many-to-many :

Error message

Error transforming many-to-many : 

What it means

Thrown by HbmXmlTransformer when transforming a <many-to-many/> collection fails. Note the two code paths in the source: many-to-many with unique="true" is routed through transformManyToManyToOneToMany and still lands in this catch. The wrapped cause and the Origin identify the real failure.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java:2231

				else if ( hbmCollection.getOneToMany() != null ) {
					try {
						attributes.getOneToManyAttributes().add( transformOneToMany( hbmCollection, propertyInfo ) );
					}
					catch (Exception e) {
						throw new TransformationException( "Error transforming one-to-many : " + hbmCollection.getName(), e, origin() );
					}
				}
				else if ( hbmCollection.getManyToMany() != null ) {
					try {
						if ( hbmCollection.getManyToMany().isUnique() ) {
							attributes.getOneToManyAttributes().add( transformManyToManyToOneToMany( hbmCollection, propertyInfo ) );
						}
						else {
							attributes.getManyToManyAttributes().add( transformManyToMany( hbmCollection, propertyInfo ) );
						}
					}
					catch (Exception e) {
						throw new TransformationException( "Error transforming many-to-many : " + hbmCollection.getName(), e, origin() );
					}
				}
				else if ( hbmCollection.getManyToAny() != null ) {
					try {
						attributes.getPluralAnyMappingAttributes().add( transformPluralAny( hbmCollection ) );
					}
					catch (Exception e) {
						throw new TransformationException( "Error transforming many-to-any : " + hbmCollection.getName(), e, origin() );
					}
				}
				else {
					throw new UnsupportedOperationException( "Unexpected node type - " + hbmCollection );
				}
			}
		}
	}

	private JaxbBasicImpl transformBasicAttribute(final JaxbHbmBasicAttributeType hbmProp, PropertyInfo propertyInfo) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Check exception.getCause() for the concrete failure
  2. Verify the many-to-many 'class' attribute resolves to a mapped entity in the same run
  3. If unique="true" is set, consider whether the mapping is really a one-to-many and rewrite it as such before transforming
  4. Validate join table, key and order-by/foreign-key declarations on both sides of the association
  5. Fall back to binding the original hbm.xml natively when the transformer cannot express the mapping

Example fix

<!-- before: unique m2m that the transformer reinterprets -->
<set name="perms" table="user_perm" unique="true">
    <key column="user_id"/>
    <many-to-many class="com.acme.Perm" column="perm_id"/>
</set>

<!-- after: express it as the one-to-many it really is -->
<set name="perms" inverse="true">
    <key column="user_id"/>
    <one-to-many class="com.acme.Perm"/>
</set>
Defensive patterns

Strategy: try-catch

Validate before calling

// flag unique="true" many-to-many ahead of time - the transformer reinterprets them
var m2m = doc.getElementsByTagName("many-to-many");
for (int i = 0; i < m2m.getLength(); i++) {
    var parent = (org.w3c.dom.Element) m2m.item(i).getParentNode();
    if ("true".equals(((org.w3c.dom.Element) m2m.item(i)).getAttribute("unique"))) {
        warn("many-to-many with unique=true on '" + parent.getAttribute("name") + "' - rewrite as one-to-many before transform");
    }
}

Try / catch

try {
    transformer.transform(hbmSource);
} catch (TransformationException e) {
    log.error("many-to-many transform failed: {}", e.getMessage(), e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: Transforming a plural attribute with a <many-to-many> child where the target class cannot be resolved, the join table/column configuration is invalid, or (unique="true") the one-to-many reinterpretation fails because no usable inverse mapping can be derived.

Common situations: Migrating association-heavy legacy schemas; unique="true" many-to-many mappings that the transformer tries to reinterpret as one-to-many; target entity of the association not included in the transformation set.

Related errors


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