hibernate/hibernate-orm · error · UnsupportedMappingException
@SoftDelete cannot be applied to @OneToMany - {}.{}
Error message
@SoftDelete cannot be applied to @OneToMany - {}.{} What it means
@SoftDelete marks an entity type as soft-deletable; it belongs on the entity class (the target of deletion), never on a @OneToMany collection property. CollectionBinder.checkAnnotations throws this UnsupportedMappingException when a one-to-many property directly carries @SoftDelete.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java:440
: new WrappedInferredData(inferredData, "element" );
}
private static void checkAnnotations(
PropertyHolder propertyHolder,
PropertyData inferredData,
MemberDetails property,
OneToMany oneToMany,
ManyToMany manyToMany,
ElementCollection elementCollection) {
if ( ( oneToMany != null || manyToMany != null || elementCollection != null )
&& isToManyAssociationWithinEmbeddableCollection( propertyHolder ) ) {
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData ) +
"' belongs to an '@Embeddable' class that is contained in an '@ElementCollection' and may not be a "
+ annotationName( oneToMany, manyToMany, elementCollection ));
}
if ( oneToMany != null && property.hasDirectAnnotationUsage( SoftDelete.class ) ) {
throw new UnsupportedMappingException(
"@SoftDelete cannot be applied to @OneToMany - " +
property.getDeclaringType().getName() + "." + property.getName()
);
}
if ( property.hasDirectAnnotationUsage( OrderColumn.class )
&& manyToMany != null
&& isNotBlank( manyToMany.mappedBy() ) ) {
throw new AnnotationException("Collection '" + getPath( propertyHolder, inferredData ) +
"' is the unowned side of a bidirectional '@ManyToMany' and may not have an '@OrderColumn'");
}
if ( manyToMany != null || elementCollection != null ) {
if ( property.hasDirectAnnotationUsage( JoinColumn.class )
|| property.hasDirectAnnotationUsage( JoinColumns.class ) ) {
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ "' is a " + annotationName( oneToMany, manyToMany, elementCollection )
+ " and is directly annotated '@JoinColumn'"View on GitHub (pinned to fad1729dce)
Solutions
- Move @SoftDelete from the @OneToMany property to the target entity class
- If several entities participate, annotate each soft-deletable entity class with @SoftDelete
- Keep the @OneToMany side free of soft-delete annotations; filtering is derived from the target entity's soft-delete setup
Example fix
// before
@Entity
class Parent {
@OneToMany(mappedBy = "parent")
@SoftDelete // error: belongs on the child entity
List<Child> children;
}
// after
@Entity
@SoftDelete
public class Child {
@ManyToOne
Parent parent;
}
@Entity
class Parent {
@OneToMany(mappedBy = "parent")
List<Child> children;
} Defensive patterns
Strategy: validation
Validate before calling
// Reject @SoftDelete placed on @OneToMany properties before boot
static void checkSoftDeletePlacement(Class<?>... entities) {
for ( Class<?> c : entities ) {
for ( Field f : c.getDeclaredFields() ) {
if ( f.isAnnotationPresent( SoftDelete.class )
&& f.isAnnotationPresent( OneToMany.class ) ) {
throw new IllegalStateException( "@SoftDelete on @OneToMany property: "
+ c.getName() + "." + f.getName() );
}
}
}
} Prevention
- Remember @SoftDelete is a type-level concern: put it on entity classes only
- During soft-delete adoption, add an architecture test that forbids @SoftDelete on fields
- Run the bootstrap smoke test so placement errors fail CI, not production start
When it happens
Trigger: A property with @OneToMany also has a direct @SoftDelete annotation (property.hasDirectAnnotationUsage(SoftDelete.class) is true during checkAnnotations).
Common situations: Adopting Hibernate's soft-delete feature and assuming the annotation goes where deletion is observed (the collection) rather than on the deleted entity; upgrading codebases that used custom soft-delete solutions with collection-level markers.
Related errors
- Collection '{}' annotated '@NotFound' is not a '@ManyToMany'
- Property '{}' is annotated both '@OneToMany' and '@ManyToMan
- Property '%s.%s' is not a collection and may not be a '@OneT
- Error processing @TypeBinderType annotation '%s' for embedda
- Error processing @TypeBinderType annotation '%s' for entity
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7645952d2942deab.
Report an issue: GitHub.