HHH-18557 Regression in automatic association management

This commit is contained in:
Andrea Boriero 2024-09-04 13:04:11 +02:00
parent cc2b9ce35c
commit 0b3c6a130a
6 changed files with 228 additions and 5 deletions

View File

@ -11,7 +11,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker; import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker; import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
import org.hibernate.bytecode.enhance.internal.tracker.NoopCollectionTracker; import org.hibernate.bytecode.enhance.internal.tracker.NoopCollectionTracker;
@ -22,7 +21,6 @@ import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CompositeOwner; import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.ExtendedSelfDirtinessTracker; import org.hibernate.engine.spi.ExtendedSelfDirtinessTracker;
import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
@ -493,16 +491,24 @@ class CodeTemplates {
if ( getterSelf() != null ) { if ( getterSelf() != null ) {
Collection<?> c = getter( field ); Collection<?> c = getter( field );
if ( c != null ) { if ( c != null ) {
if ( c instanceof PersistentCollection<?> ) {
( (PersistentCollection) c ).queueRemoveOperation( self );
}
else {
c.remove( self ); c.remove( self );
} }
} }
} }
}
@Advice.OnMethodExit @Advice.OnMethodExit
static void exit(@Advice.This Object self, @Advice.Argument(0) Object argument, @BidirectionalAttribute String inverseAttribute) { static void exit(@Advice.This Object self, @Advice.Argument(0) Object argument, @BidirectionalAttribute String inverseAttribute) {
if ( argument != null ) { if ( argument != null ) {
Collection<Object> c = getter( argument ); Collection<Object> c = getter( argument );
if ( c != null && !c.contains( self ) ) { if ( c != null && c instanceof PersistentCollection<?> ) {
( (PersistentCollection) c ).queueAddOperation( self );
}
else if ( c != null && !c.contains( self ) ) {
c.add( self ); c.add( self );
} }
} }

View File

@ -407,6 +407,58 @@ public class PersistentBag<E> extends AbstractPersistentCollection<E> implements
} }
} }
@Override
public void queueRemoveOperation(Object o) {
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
remove( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
remove( o );
}
}
@Override
public void queueAddOperation(E o){
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
add( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
add( o );
}
}
@Override @Override
public boolean containsAll(Collection<?> c) { public boolean containsAll(Collection<?> c) {
read(); read();

View File

@ -518,7 +518,7 @@ public interface PersistentCollection<E> extends LazyInitializable {
* @return {@code true} if the collection is newly instantiated * @return {@code true} if the collection is newly instantiated
*/ */
default boolean isNewlyInstantiated() { default boolean isNewlyInstantiated() {
return getKey() == null && !isDirty(); return false;
} }
/** /**
@ -527,4 +527,13 @@ public interface PersistentCollection<E> extends LazyInitializable {
default String render() { default String render() {
return getRole() + "#" + getKey() + "(initialized: " + wasInitialized() + ")"; return getRole() + "#" + getKey() + "(initialized: " + wasInitialized() + ")";
} }
default void queueRemoveOperation(Object o){
}
default void queueAddOperation(E o){
}
} }

View File

@ -181,6 +181,58 @@ public class PersistentIdentifierBag<E> extends AbstractPersistentCollection<E>
} }
} }
@Override
public void queueRemoveOperation(Object o) {
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
remove( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
remove( o );
}
}
@Override
public void queueAddOperation(E o){
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
add( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
add( o );
}
}
@Override @Override
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
if ( c.size() > 0 ) { if ( c.size() > 0 ) {

View File

@ -219,6 +219,58 @@ public class PersistentList<E> extends AbstractPersistentCollection<E> implement
} }
} }
@Override
public void queueRemoveOperation(Object o) {
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
remove( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
remove( o );
}
}
@Override
public void queueAddOperation(E o){
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
add( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
add( o );
}
}
@Override @Override
public boolean containsAll(Collection<?> coll) { public boolean containsAll(Collection<?> coll) {
read(); read();

View File

@ -225,6 +225,58 @@ public class PersistentSet<E> extends AbstractPersistentCollection<E> implements
} }
} }
@Override
public void queueRemoveOperation(Object o) {
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
remove( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
remove( o );
}
}
@Override
public void queueAddOperation(E o){
if ( !isInitialized() ) {
final DelayedOperation operation = new DelayedOperation() {
@Override
public void operate() {
add( o );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return null;
}
};
queueOperation( operation );
}
else {
add( o );
}
}
@Override @Override
public boolean containsAll(Collection<?> coll) { public boolean containsAll(Collection<?> coll) {
read(); read();