From 76f92bd901e1c8846854821aa2ed3b5083a70503 Mon Sep 17 00:00:00 2001 From: Gavin Date: Sun, 27 Nov 2022 01:58:09 +0100 Subject: [PATCH] HHH-15770 add in all the commonly-supported OnDeleteActions --- .../hibernate/annotations/OnDeleteAction.java | 36 +++++++++++++------ .../org/hibernate/cfg/AnnotationBinder.java | 6 ++-- .../java/org/hibernate/cfg/BinderHelper.java | 5 +-- .../org/hibernate/cfg/OneToOneSecondPass.java | 13 +++---- .../java/org/hibernate/cfg/ToOneBinder.java | 10 +++--- .../cfg/annotations/CollectionBinder.java | 30 ++++++++-------- .../cfg/annotations/EntityBinder.java | 5 ++- .../java/org/hibernate/dialect/Dialect.java | 8 ++--- .../internal/DefaultDeleteEventListener.java | 9 ++--- .../org/hibernate/mapping/ForeignKey.java | 29 +++++++++++---- .../java/org/hibernate/mapping/ManyToOne.java | 2 +- .../org/hibernate/mapping/SimpleValue.java | 34 +++++++++++++----- .../internal/StandardForeignKeyExporter.java | 6 ++-- 13 files changed, 121 insertions(+), 72 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/OnDeleteAction.java b/hibernate-core/src/main/java/org/hibernate/annotations/OnDeleteAction.java index 29db457586..b00549af30 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/OnDeleteAction.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/OnDeleteAction.java @@ -6,7 +6,7 @@ */ package org.hibernate.annotations; -import org.hibernate.AssertionFailure; +import static java.util.Locale.ROOT; /** * Enumerates the possible actions for the {@code on delete} clause @@ -21,24 +21,38 @@ import org.hibernate.AssertionFailure; public enum OnDeleteAction { /** - * No action. The default. + * No action. The default. An error is raised if rows still reference + * the parent when the constraint is checked, possibly later in the + * transaction. */ NO_ACTION, /** * Cascade deletion of the parent to the child. */ - CASCADE; + CASCADE, + + /** + * Prevents deletion of the parent by raising an error immediately. + */ + RESTRICT, + + /** + * Set the referencing foreign key to null. + */ + SET_NULL, + + /** + * Set the referencing foreign key to its default value. + */ + SET_DEFAULT; public String getAlternativeName() { - switch (this) { - case NO_ACTION: - return "no-action"; - case CASCADE: - return "cascade"; - default: - throw new AssertionFailure("unknown action"); - } + return toString().toLowerCase(ROOT).replace('_', '-'); + } + + public String toSqlString() { + return toString().toLowerCase(ROOT).replace('_', ' '); } public static OnDeleteAction fromExternalForm(Object value) { diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index 8834d5d2dc..ae8c153902 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -1649,7 +1649,7 @@ public final class AnnotationBinder { BinderHelper.getCascadeStrategy( null, hibernateCascade, false, forcePersist ), //@Any has no cascade attribute joinColumns, - onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action(), + onDeleteAnn == null ? null : onDeleteAnn.action(), nullability, propertyHolder, inferredData, @@ -2331,7 +2331,7 @@ public final class AnnotationBinder { private static void bindAny( String cascadeStrategy, AnnotatedJoinColumns columns, - boolean cascadeOnDelete, + OnDeleteAction onDeleteAction, Nullability nullability, PropertyHolder propertyHolder, PropertyData inferredData, @@ -2350,7 +2350,7 @@ public final class AnnotationBinder { getOverridableAnnotation( property, Formula.class, context ), columns, inferredData, - cascadeOnDelete, + onDeleteAction, lazy, nullability, propertyHolder, diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java b/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java index 177f6f72b5..293698c330 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/BinderHelper.java @@ -36,6 +36,7 @@ import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.DialectOverride; import org.hibernate.annotations.Formula; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.SqlFragmentAlias; import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XClass; @@ -1035,7 +1036,7 @@ public class BinderHelper { Formula discriminatorFormula, AnnotatedJoinColumns keyColumns, PropertyData inferredData, - boolean cascadeOnDelete, + OnDeleteAction onDeleteAction, boolean lazy, Nullability nullability, PropertyHolder propertyHolder, @@ -1046,7 +1047,7 @@ public class BinderHelper { final Any value = new Any( context, keyColumns.getTable(), true ); value.setLazy( lazy ); - value.setCascadeDeleteEnabled( cascadeOnDelete ); + value.setOnDeleteAction( onDeleteAction ); final BasicValueBinder discriminatorValueBinder = new BasicValueBinder( BasicValueBinder.Kind.ANY_DISCRIMINATOR, context ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java index a0b5c2fbb8..455594f40d 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java @@ -14,6 +14,7 @@ import org.hibernate.AnnotationException; import org.hibernate.MappingException; import org.hibernate.annotations.LazyGroup; import org.hibernate.annotations.NotFoundAction; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.boot.spi.MetadataBuildingContext; @@ -50,7 +51,7 @@ public class OneToOneSecondPass implements SecondPass { private final NotFoundAction notFoundAction; private final PropertyData inferredData; private final XClass targetEntity; - private final boolean cascadeOnDelete; + private final OnDeleteAction onDeleteAction; private final boolean optional; private final String cascadeStrategy; private final AnnotatedJoinColumns joinColumns; @@ -64,7 +65,7 @@ public class OneToOneSecondPass implements SecondPass { PropertyData inferredData, XClass targetEntity, NotFoundAction notFoundAction, - boolean cascadeOnDelete, + OnDeleteAction onDeleteAction, boolean optional, String cascadeStrategy, AnnotatedJoinColumns columns, @@ -77,7 +78,7 @@ public class OneToOneSecondPass implements SecondPass { this.notFoundAction = notFoundAction; this.inferredData = inferredData; this.targetEntity = targetEntity; - this.cascadeOnDelete = cascadeOnDelete; + this.onDeleteAction = onDeleteAction; this.optional = optional; this.cascadeStrategy = cascadeStrategy; this.joinColumns = columns; @@ -97,7 +98,7 @@ public class OneToOneSecondPass implements SecondPass { XProperty property = inferredData.getProperty(); ToOneBinder.defineFetchingStrategy( value, property, inferredData, propertyHolder ); //value.setFetchMode( fetchMode ); - value.setCascadeDeleteEnabled( cascadeOnDelete ); + value.setOnDeleteAction(onDeleteAction); //value.setLazy( fetchMode != FetchMode.JOIN ); value.setConstrained( !optional ); @@ -174,7 +175,7 @@ public class OneToOneSecondPass implements SecondPass { final ManyToOne manyToOne = new ManyToOne( buildingContext, mappedByJoin.getTable() ); //FIXME use ignore not found here manyToOne.setNotFoundAction( notFoundAction ); - manyToOne.setCascadeDeleteEnabled( oneToOne.isCascadeDeleteEnabled() ); + manyToOne.setOnDeleteAction( oneToOne.getOnDeleteAction() ); manyToOne.setFetchMode( oneToOne.getFetchMode() ); manyToOne.setLazy( oneToOne.isLazy() ); manyToOne.setReferencedEntityName( oneToOne.getReferencedEntityName() ); @@ -285,7 +286,7 @@ public class OneToOneSecondPass implements SecondPass { join.setKey( key ); //TODO support for inverse and optional join.setOptional( true ); //perhaps not quite per-spec, but a Good Thing anyway - key.setCascadeDeleteEnabled( false ); + key.setOnDeleteAction( null ); for ( Column column: otherSideProperty.getValue().getColumns() ) { Column copy = new Column(); copy.setLength( column.getLength() ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/ToOneBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/ToOneBinder.java index 59f0272d06..eff25b84c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/ToOneBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/ToOneBinder.java @@ -100,7 +100,7 @@ public class ToOneBinder { joinColumns, !mandatory, notFoundAction, - onDelete != null && OnDeleteAction.CASCADE == onDelete.action(), + onDelete == null ? null : onDelete.action(), getTargetEntity( inferredData, context ), propertyHolder, inferredData, @@ -130,7 +130,7 @@ public class ToOneBinder { AnnotatedJoinColumns joinColumns, boolean optional, NotFoundAction notFoundAction, - boolean cascadeOnDelete, + OnDeleteAction onDeleteAction, XClass targetEntity, PropertyHolder propertyHolder, PropertyData inferredData, @@ -151,7 +151,7 @@ public class ToOneBinder { defineFetchingStrategy( value, property, inferredData, propertyHolder ); //value.setFetchMode( fetchMode ); value.setNotFoundAction( notFoundAction ); - value.setCascadeDeleteEnabled( cascadeOnDelete ); + value.setOnDeleteAction( onDeleteAction ); //value.setLazy( fetchMode != FetchMode.JOIN ); if ( !optional ) { for ( AnnotatedJoinColumn column : joinColumns.getJoinColumns() ) { @@ -425,7 +425,7 @@ public class ToOneBinder { !mandatory, getFetchMode( oneToOne.fetch() ), notFoundAction, - onDelete != null && OnDeleteAction.CASCADE == onDelete.action(), + onDelete == null ? null : onDelete.action(), getTargetEntity( inferredData, context ), propertyHolder, inferredData, @@ -444,7 +444,7 @@ public class ToOneBinder { boolean optional, FetchMode fetchMode, NotFoundAction notFoundAction, - boolean cascadeOnDelete, + OnDeleteAction cascadeOnDelete, XClass targetEntity, PropertyHolder propertyHolder, PropertyData inferredData, diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java index a6e3df10e2..93cfe2094c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java @@ -212,7 +212,7 @@ public abstract class CollectionBinder { private String cacheRegionName; private boolean oneToMany; protected IndexColumn indexColumn; - protected boolean cascadeDeleteEnabled; + protected OnDeleteAction onDeleteAction; protected String mapKeyPropertyName; private boolean insertable = true; private boolean updatable = true; @@ -288,7 +288,7 @@ public abstract class CollectionBinder { collectionBinder.setAccessType( inferredData.getDefaultAccess() ); collectionBinder.setEmbedded( property.isAnnotationPresent( Embedded.class ) ); collectionBinder.setProperty( property ); - collectionBinder.setCascadeDeleteEnabled( hasOnDeleteCascade( property ) ); + collectionBinder.setOnDeleteActionAction( onDeleteAction( property ) ); collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass ); collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() ); @@ -394,9 +394,9 @@ public abstract class CollectionBinder { ); } - private static boolean hasOnDeleteCascade(XProperty property) { + private static OnDeleteAction onDeleteAction(XProperty property) { final OnDelete onDelete = property.getAnnotation( OnDelete.class ); - return onDelete != null && OnDeleteAction.CASCADE == onDelete.action(); + return onDelete == null ? null : onDelete.action(); } private static PropertyData virtualPropertyData(PropertyData inferredData, XProperty property) { @@ -1631,7 +1631,7 @@ public abstract class CollectionBinder { handleWhere( false ); final PersistentClass targetEntity = persistentClasses.get( getElementType().getName() ); - bindCollectionSecondPass( targetEntity, foreignJoinColumns, cascadeDeleteEnabled ); + bindCollectionSecondPass( targetEntity, foreignJoinColumns, onDeleteAction); if ( !collection.isInverse() && !collection.getKey().isNullable() ) { createOneToManyBackref( oneToMany ); @@ -1906,7 +1906,7 @@ public abstract class CollectionBinder { private DependantValue buildCollectionKey( Collection collection, AnnotatedJoinColumns joinColumns, - boolean cascadeDeleteEnabled, + OnDeleteAction onDeleteAction, boolean noConstraintByDefault, XProperty property, PropertyHolder propertyHolder) { @@ -1928,7 +1928,7 @@ public abstract class CollectionBinder { final List columns = joinColumns.getColumns(); key.setNullable( columns.isEmpty() || columns.get(0).isNullable() ); key.setUpdateable( columns.isEmpty() || columns.get(0).isUpdatable() ); - key.setCascadeDeleteEnabled( cascadeDeleteEnabled ); + key.setOnDeleteAction( onDeleteAction ); collection.setKey( key ); if ( property != null ) { @@ -2088,7 +2088,7 @@ public abstract class CollectionBinder { bindFilters( isCollectionOfEntities ); handleWhere( isCollectionOfEntities ); - bindCollectionSecondPass( targetEntity, joinColumns, cascadeDeleteEnabled ); + bindCollectionSecondPass( targetEntity, joinColumns, onDeleteAction); if ( isCollectionOfEntities ) { final ManyToOne element = handleCollectionOfEntities( @@ -2106,7 +2106,7 @@ public abstract class CollectionBinder { handleManyToAny( collection, inverseJoinColumns, - cascadeDeleteEnabled, + onDeleteAction, property, buildingContext ); @@ -2356,7 +2356,7 @@ public abstract class CollectionBinder { private void handleManyToAny( Collection collection, AnnotatedJoinColumns inverseJoinColumns, - boolean cascadeDeleteEnabled, + OnDeleteAction onDeleteAction, XProperty property, MetadataBuildingContext buildingContext) { //@ManyToAny @@ -2381,7 +2381,7 @@ public abstract class CollectionBinder { discriminatorFormulaAnn, inverseJoinColumns, inferredData, - cascadeDeleteEnabled, + onDeleteAction, anyAnn.fetch() == LAZY, Nullability.NO_CONSTRAINT, propertyHolder, @@ -2579,7 +2579,7 @@ public abstract class CollectionBinder { private void bindCollectionSecondPass( PersistentClass targetEntity, AnnotatedJoinColumns joinColumns, - boolean cascadeDeleteEnabled) { + OnDeleteAction onDeleteAction) { if ( !hasMappedBy() ) { createSyntheticPropertyReference( @@ -2596,7 +2596,7 @@ public abstract class CollectionBinder { final DependantValue key = buildCollectionKey( collection, joinColumns, - cascadeDeleteEnabled, + onDeleteAction, buildingContext.getBuildingOptions().isNoConstraintByDefault(), property, propertyHolder @@ -2617,8 +2617,8 @@ public abstract class CollectionBinder { key.sortProperties(); } - public void setCascadeDeleteEnabled(boolean onDeleteCascade) { - this.cascadeDeleteEnabled = onDeleteCascade; + public void setOnDeleteActionAction(OnDeleteAction onDeleteAction) { + this.onDeleteAction = onDeleteAction; } String safeCollectionRole() { diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java index 2411b3b7fe..31d7e42fb8 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java @@ -58,7 +58,6 @@ import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Loader; import org.hibernate.annotations.NaturalIdCache; import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OptimisticLockType; import org.hibernate.annotations.OptimisticLocking; import org.hibernate.annotations.Persister; @@ -672,7 +671,7 @@ public class EntityBinder { jsc.setKey( key ); handleForeignKeys( annotatedClass, context, key ); final OnDelete onDelete = annotatedClass.getAnnotation( OnDelete.class ); - key.setCascadeDeleteEnabled( onDelete != null && OnDeleteAction.CASCADE == onDelete.action() ); + key.setOnDeleteAction( onDelete == null ? null : onDelete.action() ); //we are never in a second pass at that stage, so queue it context.getMetadataCollector() .addSecondPass( new JoinedSubclassFkSecondPass( jsc, joinColumns, key, context) ); @@ -1732,7 +1731,7 @@ public class EntityBinder { DependantValue key = new DependantValue( context, join.getTable(), persistentClass.getIdentifier() ); join.setKey( key ); setForeignKeyNameIfDefined( join ); - key.setCascadeDeleteEnabled( false ); + key.setOnDeleteAction( null ); TableBinder.bindForeignKey( persistentClass, null, joinColumns, key, false, context ); key.sortProperties(); join.createPrimaryKey(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index c996e88fce..ba55b3b901 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -2923,7 +2923,7 @@ public abstract class Dialect implements ConversionContext { /** * Does this dialect support column-level check constraints? * - * @return True if column-level {@code CHECK} constraints are supported; + * @return True if column-level {@code check} constraints are supported; * false otherwise. */ public boolean supportsColumnCheck() { @@ -2933,7 +2933,7 @@ public abstract class Dialect implements ConversionContext { /** * Does this dialect support table-level check constraints? * - * @return True if table-level {@code CHECK} constraints are supported; + * @return True if table-level {@code check} constraints are supported; * false otherwise. */ public boolean supportsTableCheck() { @@ -2941,9 +2941,9 @@ public abstract class Dialect implements ConversionContext { } /** - * Does this dialect support cascaded delete on foreign key definitions? + * Does this dialect support {@code on delete} actions in foreign key definitions? * - * @return {@code true} indicates that the dialect does support cascaded delete on foreign keys. + * @return {@code true} if the dialect does support the {@code on delete} clause. */ public boolean supportsCascadeDelete() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java index 3fb3b37e0f..080ac1f2f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java @@ -168,7 +168,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); if ( ForeignKeys.isTransient( persister.getEntityName(), entity, null, source ) ) { - deleteTransientEntity( source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities ); + deleteTransientEntity( source, entity, persister, transientEntities ); } else { performDetachedEntityDeletionCheck( event ); @@ -320,7 +320,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback * * @param session The session which is the source of the event * @param entity The entity being delete processed - * @param cascadeDeleteEnabled Is cascading of deletes enabled * @param persister The entity persister * @param transientEntities A cache of already visited transient entities * (to avoid infinite recursion). @@ -328,7 +327,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback protected void deleteTransientEntity( EventSource session, Object entity, - boolean cascadeDeleteEnabled, EntityPersister persister, DeleteContext transientEntities) { LOG.handlingTransientEntity(); @@ -336,7 +334,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback LOG.trace( "Already handled transient entity; skipping" ); return; } - cascadeBeforeDelete( session, persister, entity, null, transientEntities ); + cascadeBeforeDelete( session, persister, entity, transientEntities ); cascadeAfterDelete( session, persister, entity, transientEntities ); } @@ -390,7 +388,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback persistenceContext.setEntryStatus( entityEntry, Status.DELETED ); final EntityKey key = session.generateEntityKey( entityEntry.getId(), persister ); - cascadeBeforeDelete( session, persister, entity, entityEntry, transientEntities ); + cascadeBeforeDelete( session, persister, entity, transientEntities ); new ForeignKeys.Nullifier( entity, true, false, session, persister ) .nullifyTransientReferences( entityEntry.getDeletedState() ); @@ -493,7 +491,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback EventSource session, EntityPersister persister, Object entity, - EntityEntry entityEntry, DeleteContext transientEntities) throws HibernateException { CacheMode cacheMode = session.getCacheMode(); diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/ForeignKey.java b/hibernate-core/src/main/java/org/hibernate/mapping/ForeignKey.java index 5ec38240e5..567edab0d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/ForeignKey.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/ForeignKey.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.List; import org.hibernate.MappingException; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.dialect.Dialect; import org.hibernate.internal.util.StringHelper; @@ -24,7 +25,7 @@ public class ForeignKey extends Constraint { private Table referencedTable; private String referencedEntityName; private String keyDefinition; - private boolean cascadeDeleteEnabled; + private OnDeleteAction onDeleteAction; private final List referencedColumns = new ArrayList<>(); private boolean creationEnabled = true; @@ -90,8 +91,8 @@ public class ForeignKey extends Constraint { isReferenceToPrimaryKey() ); - return cascadeDeleteEnabled && dialect.supportsCascadeDelete() - ? result + " on delete cascade" + return onDeleteAction != null && onDeleteAction != OnDeleteAction.NO_ACTION && dialect.supportsCascadeDelete() + ? result + " on delete " + onDeleteAction.toSqlString() : result; } @@ -166,12 +167,28 @@ public class ForeignKey extends Constraint { this.keyDefinition = keyDefinition; } - public boolean isCascadeDeleteEnabled() { - return cascadeDeleteEnabled; + public void setOnDeleteAction(OnDeleteAction onDeleteAction) { + this.onDeleteAction = onDeleteAction; } + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; + } + + /** + * @deprecated use {@link #getOnDeleteAction()} + */ + @Deprecated(since = "6.2") + public boolean isCascadeDeleteEnabled() { + return onDeleteAction == OnDeleteAction.CASCADE; + } + + /** + * @deprecated use {@link #setOnDeleteAction(OnDeleteAction)} + */ + @Deprecated(since = "6.2") public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { - this.cascadeDeleteEnabled = cascadeDeleteEnabled; + this.onDeleteAction = cascadeDeleteEnabled ? OnDeleteAction.CASCADE : OnDeleteAction.NO_ACTION; } public boolean isPhysicalConstraint() { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/ManyToOne.java b/hibernate-core/src/main/java/org/hibernate/mapping/ManyToOne.java index a826ea1046..68cf7cd8c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/ManyToOne.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/ManyToOne.java @@ -105,7 +105,7 @@ public class ManyToOne extends ToOne { getForeignKeyDefinition(), new ArrayList<>( property.getColumns() ) ); - fk.setCascadeDeleteEnabled( isCascadeDeleteEnabled() ); + fk.setOnDeleteAction( getOnDeleteAction() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index c57d45c7c9..693d97c3a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -24,6 +24,7 @@ import org.hibernate.FetchMode; import org.hibernate.MappingException; import org.hibernate.Remove; import org.hibernate.TimeZoneStorageStrategy; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor; import org.hibernate.boot.model.convert.spi.ConverterDescriptor; @@ -96,7 +97,7 @@ public abstract class SimpleValue implements KeyValue { private String foreignKeyName; private String foreignKeyDefinition; private boolean alternateUniqueKey; - private boolean cascadeDeleteEnabled; + private OnDeleteAction onDeleteAction; private boolean foreignKeyEnabled = true; private ConverterDescriptor attributeConverterDescriptor; @@ -130,7 +131,7 @@ public abstract class SimpleValue implements KeyValue { this.foreignKeyName = original.foreignKeyName; this.foreignKeyDefinition = original.foreignKeyDefinition; this.alternateUniqueKey = original.alternateUniqueKey; - this.cascadeDeleteEnabled = original.cascadeDeleteEnabled; + this.onDeleteAction = original.onDeleteAction; this.attributeConverterDescriptor = original.attributeConverterDescriptor; this.type = original.type; this.customIdGeneratorCreator = original.customIdGeneratorCreator; @@ -150,15 +151,32 @@ public abstract class SimpleValue implements KeyValue { return getMetadata().getMetadataBuildingOptions().getServiceRegistry(); } - @Override - public boolean isCascadeDeleteEnabled() { - return cascadeDeleteEnabled; + public void setOnDeleteAction(OnDeleteAction onDeleteAction) { + this.onDeleteAction = onDeleteAction; } - public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { - this.cascadeDeleteEnabled = cascadeDeleteEnabled; + public OnDeleteAction getOnDeleteAction() { + return onDeleteAction; } + /** + * @deprecated use {@link #getOnDeleteAction()} + */ + @Deprecated(since = "6.2") + @Override + public boolean isCascadeDeleteEnabled() { + return onDeleteAction == OnDeleteAction.CASCADE; + } + + /** + * @deprecated use {@link #setOnDeleteAction(OnDeleteAction)} + */ + @Deprecated(since = "6.2") + public void setCascadeDeleteEnabled(boolean cascadeDeleteEnabled) { + this.onDeleteAction = cascadeDeleteEnabled ? OnDeleteAction.CASCADE : OnDeleteAction.NO_ACTION; + } + + public void addColumn(Column column) { addColumn( column, true, true ); } @@ -325,7 +343,7 @@ public abstract class SimpleValue implements KeyValue { public ForeignKey createForeignKeyOfEntity(String entityName) { if ( isConstrained() ) { final ForeignKey fk = table.createForeignKey( getForeignKeyName(), getConstraintColumns(), entityName, getForeignKeyDefinition() ); - fk.setCascadeDeleteEnabled( cascadeDeleteEnabled ); + fk.setOnDeleteAction( onDeleteAction ); return fk; } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java index 50c6f71bf7..fadac880a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardForeignKeyExporter.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Locale; import org.hibernate.AssertionFailure; +import org.hibernate.annotations.OnDeleteAction; import org.hibernate.boot.Metadata; import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.dialect.Dialect; @@ -77,8 +78,9 @@ public class StandardForeignKeyExporter implements Exporter { ); if ( dialect.supportsCascadeDelete() ) { - if ( foreignKey.isCascadeDeleteEnabled() ) { - buffer.append( " on delete cascade" ); + OnDeleteAction onDeleteAction = foreignKey.getOnDeleteAction(); + if ( onDeleteAction != null && onDeleteAction != OnDeleteAction.NO_ACTION ) { + buffer.append( " on delete " ).append( onDeleteAction.toSqlString() ); } }