hibernate/hibernate-orm · error · MappingException
Attribute [%s] referenced columns from multiple tables: %s,
Error message
Attribute [%s] referenced columns from multiple tables: %s, %s
What it means
For an <component> (embedded) attribute, Hibernate walks the embeddable's attribute sources and derives the single containing table for the embedded's columns, because a component's columns must all live in one table. If two sub-attributes resolve to different non-null table names, determineTable throws this MappingException naming the attribute role and both conflicting tables.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java:1368
private Identifier determineTable(
MappingDocument sourceDocument,
String attributeName,
RelationalValueSourceContainer relationalValueSourceContainer) {
return determineTable( sourceDocument, attributeName,
relationalValueSourceContainer.getRelationalValueSources() );
}
private Identifier determineTable(
MappingDocument mappingDocument,
SingularAttributeSourceEmbedded embeddedAttributeSource) {
Identifier tableName = null;
for ( var attributeSource : embeddedAttributeSource.getEmbeddableSource().attributeSources() ) {
final Identifier determinedName =
determineTableName( mappingDocument, embeddedAttributeSource, attributeSource );
if ( determinedName != null && !determinedName.equals( tableName ) ) {
if ( tableName != null ) {
throw new MappingException(
"Attribute [%s] referenced columns from multiple tables: %s, %s"
.formatted( embeddedAttributeSource.getAttributeRole().getFullPath(),
tableName, determinedName ),
mappingDocument.getOrigin()
);
}
tableName = determinedName;
}
}
return tableName;
}
private Identifier determineTableName(MappingDocument mappingDocument, SingularAttributeSourceEmbedded embeddedAttributeSource, AttributeSource attributeSource) {
if ( attributeSource instanceof RelationalValueSourceContainer relationalValueSourceContainer ) {
return determineTable(
mappingDocument,
embeddedAttributeSource.getAttributeRole().getFullPath(),
relationalValueSourceContainerView on GitHub (pinned to fad1729dce)
Solutions
- Remove the explicit table= attributes from the component's sub-attribute columns so they all default to the containing table
- If the component genuinely belongs on a secondary table, move the whole component under the corresponding <join> element instead of naming tables per column
- After a rename, align every sub-attribute's table reference to one single table
Example fix
// before
<component name='address' class='Address'>
<property name='street' column='street' table='user_addr'/>
<property name='city' column='city' table='addresses'/>
</component>
// after
<component name='address' class='Address'>
<property name='street' column='street'/>
<property name='city' column='city'/>
</component> Defensive patterns
Strategy: validation
Validate before calling
NodeList components = doc.getElementsByTagName("component");
for (int i = 0; i < components.getLength(); i++) {
Set<String> tables = new HashSet<>();
NodeList children = components.item(i).getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
if (children.item(j) instanceof Element e && e.hasAttribute("table")) {
tables.add(e.getAttribute("table"));
}
}
if (tables.size() > 1) {
throw new IllegalStateException("component columns span tables: " + tables);
}
} Try / catch
catch (MappingException e) at SessionFactory build; the message prints the component's attribute role and the two conflicting table names - remove or align the per-column table= attributes for that component.
Prevention
- Never set table= on columns inside <component> unless the whole component targets that table
- Put components that belong to a secondary table inside the matching <join>
- Review column overrides after any table rename or entity refactor
When it happens
Trigger: A <component name='...' class='...'> whose nested <property>/<many-to-one> elements carry explicit table= attributes pointing at different tables; a component nested in a <join> (secondary table) where some sub-attributes name the primary table and others the join table.
Common situations: Copy-pasting column definitions from an entity with secondary tables into a component; stale table references left behind after table renames; moving a component between classes without cleaning per-column table overrides.
Related errors
- transformation of <any/> as part of <join/> (secondary-table
- Secondary table '${explicitTableName}' for property '${prope
- Column mappings for property '${propertyName}' mix distinct
- Collection '{}' has foreign key in secondary table
- Member '" + memberDetails.getName() + "' of embeddable class
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8bbe546ff74953ca.
Report an issue: GitHub.