Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadingAction;
Expand Down Expand Up @@ -111,6 +112,7 @@ public static <T> void cascade(
final boolean isUninitializedProperty =
hasUninitializedLazyProperties
&& !bytecodeEnhancement.isAttributeLoaded( parent, propertyName );
final boolean isCascadeDeleteEnabled = cascadeDeleteEnabled( action, persister, i );

if ( action.appliesTo( type, style ) ) {
final Object child;
Expand Down Expand Up @@ -170,7 +172,7 @@ else if ( action.performOnLazyProperty() && type instanceof EntityType ) {
style,
propertyName,
anything,
false
isCascadeDeleteEnabled
);
}
else if ( action.deleteOrphans()
Expand All @@ -186,7 +188,7 @@ && isLogicalOneToOne( type ) ) {
type,
style,
propertyName,
false
isCascadeDeleteEnabled
);
}
}
Expand Down Expand Up @@ -421,7 +423,7 @@ private static <T> void cascadeComponent(
componentPropertyStyle,
subPropertyName,
anything,
false
cascadeDeleteEnabled( action, componentType, i )
);
}
}
Expand Down Expand Up @@ -508,7 +510,7 @@ private static <T> void cascadeCollection(
style,
elemType,
anything,
persister.isCascadeDeleteEnabled()
cascadeDeleteEnabled( action, persister )
);
}
}
Expand Down Expand Up @@ -607,7 +609,8 @@ private static <T> void cascadeCollectionElements(
final PersistentCollection<?> persistentCollection =
child instanceof PersistentCollection<?> collection
? collection
: eventSource.getPersistenceContext().getCollectionHolder( child );
: eventSource.getPersistenceContextInternal()
.getCollectionHolder( child );

final boolean deleteOrphans = style.hasOrphanDelete()
&& action.deleteOrphans()
Expand Down Expand Up @@ -654,4 +657,19 @@ private static void deleteOrphans(EventSource eventSource, String entityName, Pe
}
}
}

private static <T> boolean cascadeDeleteEnabled(CascadingAction<T> action, CollectionPersister persister) {
return action.directionAffectedByCascadeDelete() == ForeignKeyDirection.FROM_PARENT
&& persister.isCascadeDeleteEnabled();
}

private static <T> boolean cascadeDeleteEnabled(CascadingAction<T> action, EntityPersister persister, int i) {
return action.directionAffectedByCascadeDelete() == ForeignKeyDirection.TO_PARENT
&& persister.getEntityMetamodel().getPropertyOnDeleteActions()[i] == OnDeleteAction.CASCADE;
}

private static <T> boolean cascadeDeleteEnabled(CascadingAction<T> action, CompositeType componentType, int i) {
return action.directionAffectedByCascadeDelete() == ForeignKeyDirection.TO_PARENT
&& componentType.getOnDeleteAction( i ) == OnDeleteAction.CASCADE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
import java.util.List;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.Incubating;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.event.spi.EventSource;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type;

/**
* A session action that may be cascaded from parent entity to its children
*
* @param <T> The type of some context propagated with the cascading action
*
* @author Gavin King
* @author Steve Ebersole
*/
Expand All @@ -32,9 +36,9 @@ public interface CascadingAction<T> {
* @param parentEntityName The name of the parent entity
* @param propertyName The name of the attribute of the parent entity being cascaded
* @param attributePath The full path of the attribute of the parent entity being cascaded
* @param anything Anything ;) Typically some form of cascade-local cache
* which is specific to each {@link CascadingAction} type
* @param isCascadeDeleteEnabled Are cascading deletes enabled.
* @param anything Some context specific to the kind of {@link CascadingAction}
* @param isCascadeDeleteEnabled Whether the foreign key is declared with
* {@link org.hibernate.annotations.OnDeleteAction#CASCADE on delete cascade}.
*/
void cascade(
EventSource session,
Expand Down Expand Up @@ -111,4 +115,17 @@ boolean cascadeNow(
CascadePoint cascadePoint,
AssociationType associationType,
SessionFactoryImplementor factory);

/**
* The cascade direction in which we care whether the foreign key is declared with
* {@link org.hibernate.annotations.OnDeleteAction#CASCADE on delete cascade}.
*
* @apiNote This allows us to reuse the long-existing boolean parameter of
* {@link #cascade(EventSource,Object,String,String,String,List,Object,boolean)}
* for multiple purposes.
*
* @since 7
*/
@Incubating @Nullable
ForeignKeyDirection directionAffectedByCascadeDelete();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
package org.hibernate.engine.spi;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.HibernateException;
import org.hibernate.Internal;
import org.hibernate.LockMode;
Expand All @@ -21,6 +22,7 @@
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.Type;
Expand Down Expand Up @@ -89,6 +91,11 @@ public boolean anythingToCascade(EntityPersister persister) {
return persister.hasCascadeDelete();
}

@Override
public ForeignKeyDirection directionAffectedByCascadeDelete() {
return ForeignKeyDirection.FROM_PARENT;
}

@Override
public String toString() {
return "ACTION_DELETE";
Expand Down Expand Up @@ -387,7 +394,7 @@ public void cascade(
Void nothing,
boolean isCascadeDeleteEnabled)
throws HibernateException {
if ( child != null && isChildTransient( session, child, childEntityName ) ) {
if ( child != null && isChildTransient( session, child, childEntityName, isCascadeDeleteEnabled ) ) {
throw new TransientPropertyValueException(
"Persistent instance of '" + parentEntityName
+ "' references an unsaved transient instance of '" + childEntityName
Expand Down Expand Up @@ -481,13 +488,18 @@ public boolean performOnLazyProperty() {
return false;
}

@Override
public ForeignKeyDirection directionAffectedByCascadeDelete() {
return ForeignKeyDirection.TO_PARENT;
}

@Override
public String toString() {
return "ACTION_CHECK_ON_FLUSH";
}
};

private static boolean isChildTransient(EventSource session, Object child, String entityName) {
private static boolean isChildTransient(EventSource session, Object child, String entityName, boolean isCascadeDeleteEnabled) {
if ( isHibernateProxy( child ) ) {
// a proxy is always non-transient
// and ForeignKeys.isTransient()
Expand All @@ -502,7 +514,11 @@ private static boolean isChildTransient(EventSource session, Object child, Strin
// we are good, even if it's not yet
// inserted, since ordering problems
// are detected and handled elsewhere
return entry.getStatus().isDeletedOrGone();
return entry.getStatus().isDeletedOrGone()
// if the foreign key is 'on delete cascade'
// we don't have to throw because the database
// will delete the parent for us
&& !isCascadeDeleteEnabled;
}
else {
// TODO: check if it is a merged entity which has not yet been flushed
Expand Down Expand Up @@ -580,6 +596,11 @@ public boolean cascadeNow(
SessionFactoryImplementor factory) {
return associationType.getForeignKeyDirection().cascadeNow( cascadePoint );
}

@Override @Nullable
public ForeignKeyDirection directionAffectedByCascadeDelete() {
return null;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.hibernate.Internal;
import org.hibernate.MappingException;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
Expand Down Expand Up @@ -139,6 +140,10 @@ public void resetOptional(boolean optional) {
}
}

public OnDeleteAction getOnDeleteAction() {
return value instanceof ToOne toOne ? toOne.getOnDeleteAction() : null;
}

public CascadeStyle getCascadeStyle() throws MappingException {
final Type type = value.getType();
if ( type instanceof AnyType ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.hibernate.tuple;

import org.hibernate.FetchMode;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.AttributeSource;
Expand Down Expand Up @@ -92,6 +93,11 @@ public CascadeStyle getCascadeStyle() {
return attributeInformation.getCascadeStyle();
}

@Override
public OnDeleteAction getOnDeleteAction() {
return attributeInformation.getOnDeleteAction();
}

@Override
public FetchMode getFetchMode() {
return attributeInformation.getFetchMode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.hibernate.tuple;

import org.hibernate.FetchMode;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.engine.spi.CascadeStyle;

/**
Expand All @@ -19,6 +20,7 @@ public class BaselineAttributeInformation {
private final boolean nullable;
private final boolean dirtyCheckable;
private final boolean versionable;
private final OnDeleteAction onDeleteAction;
private final CascadeStyle cascadeStyle;
private final FetchMode fetchMode;

Expand All @@ -30,6 +32,7 @@ public BaselineAttributeInformation(
boolean dirtyCheckable,
boolean versionable,
CascadeStyle cascadeStyle,
OnDeleteAction onDeleteAction,
FetchMode fetchMode) {
this.lazy = lazy;
this.insertable = insertable;
Expand All @@ -38,6 +41,7 @@ public BaselineAttributeInformation(
this.dirtyCheckable = dirtyCheckable;
this.versionable = versionable;
this.cascadeStyle = cascadeStyle;
this.onDeleteAction = onDeleteAction;
this.fetchMode = fetchMode;
}

Expand Down Expand Up @@ -73,6 +77,10 @@ public FetchMode getFetchMode() {
return fetchMode;
}

public OnDeleteAction getOnDeleteAction() {
return onDeleteAction;
}

public static class Builder {
private boolean lazy;
private boolean insertable;
Expand All @@ -81,6 +89,7 @@ public static class Builder {
private boolean dirtyCheckable;
private boolean versionable;
private CascadeStyle cascadeStyle;
private OnDeleteAction onDeleteAction;
private FetchMode fetchMode;

public Builder setLazy(boolean lazy) {
Expand Down Expand Up @@ -118,6 +127,11 @@ public Builder setCascadeStyle(CascadeStyle cascadeStyle) {
return this;
}

public Builder setOnDeleteAction(OnDeleteAction onDeleteAction) {
this.onDeleteAction = onDeleteAction;
return this;
}

public Builder setFetchMode(FetchMode fetchMode) {
this.fetchMode = fetchMode;
return this;
Expand All @@ -132,6 +146,7 @@ public BaselineAttributeInformation createInformation() {
dirtyCheckable,
versionable,
cascadeStyle,
onDeleteAction,
fetchMode
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.hibernate.tuple;

import org.hibernate.FetchMode;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.engine.spi.CascadeStyle;

/**
Expand Down Expand Up @@ -32,5 +33,7 @@ public interface NonIdentifierAttribute extends Attribute {

CascadeStyle getCascadeStyle();

OnDeleteAction getOnDeleteAction();

FetchMode getFetchMode();
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public static VersionProperty buildVersionProperty(
.setDirtyCheckable( property.isUpdateable() && !lazy )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setOnDeleteAction( property.getOnDeleteAction() )
.createInformation()
);
}
Expand Down Expand Up @@ -169,6 +170,7 @@ public static NonIdentifierAttribute buildEntityBasedAttribute(
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setOnDeleteAction( property.getOnDeleteAction() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
Expand All @@ -188,6 +190,7 @@ public static NonIdentifierAttribute buildEntityBasedAttribute(
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setOnDeleteAction( property.getOnDeleteAction() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
Expand All @@ -209,6 +212,7 @@ public static NonIdentifierAttribute buildEntityBasedAttribute(
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setOnDeleteAction( property.getOnDeleteAction() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.hibernate.tuple;

import org.hibernate.FetchMode;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.type.Type;

Expand Down Expand Up @@ -37,6 +38,7 @@ public StandardProperty(
boolean checkable,
boolean versionable,
CascadeStyle cascadeStyle,
OnDeleteAction onDeleteAction,
FetchMode fetchMode) {
super(
null,
Expand All @@ -52,6 +54,7 @@ public StandardProperty(
.setDirtyCheckable( checkable )
.setVersionable( versionable )
.setCascadeStyle( cascadeStyle )
.setOnDeleteAction( onDeleteAction )
.setFetchMode( fetchMode )
.createInformation()
);
Expand Down
Loading
Loading