Skip to content

Commit 7b43dda

Browse files
committed
HHH-19508 sort CollectionUpdateActions to move those with deletes to front of the line
1 parent 9ed9bda commit 7b43dda

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

hibernate-core/src/main/java/org/hibernate/action/internal/CollectionUpdateAction.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.hibernate.AssertionFailure;
88
import org.hibernate.HibernateException;
99
import org.hibernate.collection.spi.PersistentCollection;
10+
import org.hibernate.engine.spi.ComparableExecutable;
1011
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1112
import org.hibernate.event.monitor.spi.EventMonitor;
1213
import org.hibernate.event.spi.EventSource;
@@ -107,6 +108,23 @@ else if ( collection.needsRecreate( persister ) ) {
107108
}
108109
}
109110

111+
@Override
112+
public int compareTo(ComparableExecutable o) {
113+
if ( o instanceof CollectionUpdateAction that
114+
&& getPrimarySortClassifier().equals( o.getPrimarySortClassifier() ) ) {
115+
final CollectionPersister persister = getPersister();
116+
boolean hasDeletes = this.getCollection().getDeletes( persister, false ).hasNext();
117+
boolean otherHasDeletes = that.getCollection().getDeletes( persister, false ).hasNext();
118+
if ( hasDeletes && !otherHasDeletes ) {
119+
return -1;
120+
}
121+
if ( otherHasDeletes && !hasDeletes ) {
122+
return 1;
123+
}
124+
}
125+
return super.compareTo( o );
126+
}
127+
110128
private void preUpdate() {
111129
getEventListenerGroups().eventListenerGroup_PRE_COLLECTION_UPDATE
112130
.fireLazyEventOnEachListener( this::newPreCollectionUpdateEvent,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.actionqueue;
6+
7+
import jakarta.persistence.CascadeType;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.OneToMany;
11+
import org.hibernate.cfg.BatchSettings;
12+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
13+
import org.hibernate.testing.orm.junit.Jpa;
14+
import org.hibernate.testing.orm.junit.Setting;
15+
import org.junit.jupiter.api.Test;
16+
17+
import java.util.HashSet;
18+
import java.util.Set;
19+
20+
@Jpa(annotatedClasses =
21+
{CollectionUpdateOrderingTest.Thing.class,
22+
CollectionUpdateOrderingTest.OtherThing.class},
23+
integrationSettings = @Setting(name = BatchSettings.ORDER_UPDATES, value = "true"))
24+
class CollectionUpdateOrderingTest {
25+
26+
@Test
27+
void test(EntityManagerFactoryScope scope) {
28+
scope.inTransaction( session -> {
29+
Thing thing1 = new Thing();
30+
Thing thing2 = new Thing();
31+
thing2.id = 2;
32+
thing1.id = 3; //bigger
33+
OtherThing otherThing1 = new OtherThing();
34+
OtherThing otherThing2 = new OtherThing();
35+
otherThing1.id = 1;
36+
otherThing2.id = 2;
37+
thing1.otherThings.add(otherThing1);
38+
thing1.otherThings.add(otherThing2);
39+
session.persist( thing1 );
40+
session.persist( thing2 );
41+
} );
42+
scope.inTransaction( session -> {
43+
Thing thing2 = session.find(Thing.class, 2L);
44+
Thing thing1 = session.find(Thing.class, 3L);
45+
OtherThing otherThing = thing1.otherThings.iterator().next();
46+
thing1.otherThings.remove(otherThing);
47+
thing2.otherThings.add(otherThing);
48+
});
49+
}
50+
51+
@Entity
52+
static class Thing {
53+
@Id long id;
54+
@OneToMany(cascade = CascadeType.PERSIST)
55+
Set<OtherThing> otherThings = new HashSet<>();
56+
}
57+
58+
@Entity
59+
static class OtherThing {
60+
@Id long id;
61+
}
62+
}

0 commit comments

Comments
 (0)