hibernate/hibernate-orm · error · AnnotationException
Column mappings for property '${propertyName}' mix updatable
Error message
Column mappings for property '${propertyName}' mix updatable with 'updatable=false' What it means
Hibernate throws this at bootstrap while binding a property that maps to multiple columns (e.g. via @Columns, @JoinColumn + @Column, or overridden mappings). Every column mapping belonging to one property must agree on nullability, insertability, updatability, and secondary table; here two of them disagree on the 'updatable' flag, so Hibernate cannot decide what the UPDATE statements should include.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumns.java:174
public void checkPropertyConsistency() {
if ( columns.size() > 1 ) {
for ( int currentIndex = 1; currentIndex < columns.size(); currentIndex++ ) {
final AnnotatedColumn current = columns.get( currentIndex );
final AnnotatedColumn previous = columns.get( currentIndex - 1 );
if ( !current.isFormula() && !previous.isFormula() ) {
if ( current.isNullable() != previous.isNullable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix nullable with 'not null'"
);
}
if ( current.isInsertable() != previous.isInsertable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix insertable with 'insertable=false'"
);
}
if ( current.isUpdatable() != previous.isUpdatable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix updatable with 'updatable=false'"
);
}
if ( !current.getExplicitTableName().equals( previous.getExplicitTableName() ) ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix distinct secondary tables"
);
}
}
}
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Find the property named in the message and set the SAME 'updatable' value on every @Column/@JoinColumn that maps it (default is true).
- Check @AttributeOverride / @AssociationOverride declarations in subclasses and embeddings for flags that differ from the parent mapping; make them consistent.
- If one column really must be read-only while others are writable, split them into two properties (one with updatable=false) instead of one property with mixed flags.
Example fix
// before
@Entity
class Person {
@Columns({
@Column(name = "first_name"),
@Column(name = "last_name", updatable = false) // mixed flags
})
private Name name;
}
// after
@Entity
class Person {
@Columns({
@Column(name = "first_name"),
@Column(name = "last_name") // consistent: both updatable
})
private Name name;
} Defensive patterns
Strategy: validation
Validate before calling
// Startup self-check: fail with a clear report before Hibernate binds
for (Class<?> cls : persistenceUnitClasses) {
for (Field f : cls.getDeclaredFields()) {
Column[] cols = f.getAnnotationsByType(Column.class);
Set<Boolean> upd = Arrays.stream(cols).map(Column::updatable).collect(toSet());
if (cols.length > 1 && upd.size() > 1) {
throw new IllegalStateException(cls.getSimpleName() + "." + f.getName()
+ " mixes updatable flags across " + cols.length + " columns");
}
}
} Try / catch
try {
Metadata metadata = metadataBuilder.build(); // binding happens here
} catch (AnnotationException e) {
// message names the property: "Column mappings for property 'x' mix updatable..."
throw newConfigurationException("Inconsistent column flags", e);
} Prevention
- Whenever a property maps multiple columns, always specify ALL of nullable/insertable/updatable/table explicitly on every column.
- Review @AttributeOverride/@AssociationOverride values in subclasses whenever flags change on the parent mapping.
- Add a metadata smoke test that builds a SessionFactory for all entities so these errors surface in CI, not production.
When it happens
Trigger: A property carries two column mappings where one is 'updatable=true' (the default) and the other is '@Column(..., updatable=false)'. Typical shapes: an @AttributeOverride/@AssociationOverride in a subclass that flips updatable on one column of a multi-column property; a @Column plus a @JoinColumn (or @JoinColumns) on the same association with mismatched flags; the same property mapped twice through an embedded and an override.
Common situations: Copying a read-only pattern ('insertable=false, updatable=false') onto only the first of several @Column entries of a property; overriding an embedded or mapped-superclass mapping in a subclass without repeating all flags; mixing JPA annotations with legacy XML hbm mappings where one side sets updatable=false.
Related errors
- Column mappings for property '${propertyName}' mix distinct
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
- Collection '<propertyName>' was annotated '@Collate'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/74119d31513cd565.
Report an issue: GitHub.