Skip to content

Commit 46418f3

Browse files
committed
[#2330] Test collection events with StatelessSession
Add test from ORM issue HHH-19523
1 parent bace0f4 commit 46418f3

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive;
7+
8+
import java.util.ArrayList;
9+
import java.util.Collection;
10+
import java.util.List;
11+
import java.util.Set;
12+
13+
import org.hibernate.engine.spi.SessionFactoryImplementor;
14+
import org.hibernate.event.service.spi.EventListenerRegistry;
15+
import org.hibernate.event.spi.AbstractCollectionEvent;
16+
import org.hibernate.event.spi.EventType;
17+
import org.hibernate.event.spi.PostCollectionRecreateEvent;
18+
import org.hibernate.event.spi.PostCollectionRecreateEventListener;
19+
import org.hibernate.event.spi.PostCollectionRemoveEvent;
20+
import org.hibernate.event.spi.PostCollectionRemoveEventListener;
21+
import org.hibernate.event.spi.PreCollectionRecreateEvent;
22+
import org.hibernate.event.spi.PreCollectionRecreateEventListener;
23+
import org.hibernate.event.spi.PreCollectionRemoveEvent;
24+
import org.hibernate.event.spi.PreCollectionRemoveEventListener;
25+
26+
import org.junit.jupiter.api.Test;
27+
28+
import io.vertx.junit5.VertxTestContext;
29+
import jakarta.persistence.Column;
30+
import jakarta.persistence.Entity;
31+
import jakarta.persistence.GeneratedValue;
32+
import jakarta.persistence.GenerationType;
33+
import jakarta.persistence.Id;
34+
import jakarta.persistence.JoinColumn;
35+
import jakarta.persistence.OneToMany;
36+
import jakarta.persistence.Table;
37+
38+
import static org.assertj.core.api.Assertions.assertThat;
39+
40+
/**
41+
* Adapt test in ORM: CollectionStatelessSessionListenerTest
42+
*/
43+
public class CollectionStatelessSessionListenerTest extends BaseReactiveTest {
44+
45+
@Override
46+
protected Collection<Class<?>> annotatedEntities() {
47+
return Set.of( EntityA.class, EntityB.class );
48+
}
49+
50+
51+
@Test
52+
public void mutinyStatelessInsert(VertxTestContext context) {
53+
final List<AbstractCollectionEvent> events = new ArrayList<>();
54+
initializeListeners( events );
55+
56+
EntityA a = new EntityA();
57+
EntityB b = new EntityB();
58+
a.children.add( b );
59+
test( context, getMutinySessionFactory()
60+
.withStatelessTransaction( statelessSession -> statelessSession
61+
.insert( b )
62+
.chain( () -> statelessSession.insert( a ) )
63+
.chain( () -> statelessSession.delete( a ) )
64+
.chain( () -> statelessSession.delete( b ) )
65+
)
66+
.invoke( () -> assertEvents( events ) )
67+
);
68+
}
69+
70+
@Test
71+
public void mutinyStatelessInsertAll(VertxTestContext context) {
72+
final List<AbstractCollectionEvent> events = new ArrayList<>();
73+
initializeListeners( events );
74+
75+
EntityA a = new EntityA();
76+
EntityB b = new EntityB();
77+
a.children.add( b );
78+
test( context, getMutinySessionFactory()
79+
.withStatelessTransaction( statelessSession -> statelessSession
80+
.insertAll( b, a )
81+
.chain( () -> statelessSession.deleteAll( a, b ) )
82+
)
83+
.invoke( () -> assertEvents( events ) )
84+
);
85+
}
86+
87+
@Test
88+
public void stageStatelessInsert(VertxTestContext context) {
89+
final List<AbstractCollectionEvent> events = new ArrayList<>();
90+
initializeListeners( events );
91+
92+
EntityA a = new EntityA();
93+
EntityB b = new EntityB();
94+
a.children.add( b );
95+
test( context, getSessionFactory()
96+
.withStatelessTransaction( statelessSession -> statelessSession
97+
.insert( b )
98+
.thenCompose( v -> statelessSession.insert( a ) )
99+
.thenCompose( v -> statelessSession.delete( a ) )
100+
.thenCompose( v -> statelessSession.delete( b ) )
101+
)
102+
.thenAccept( v -> assertEvents( events ) )
103+
);
104+
}
105+
106+
@Test
107+
public void stageStatelessInsertAll(VertxTestContext context) {
108+
final List<AbstractCollectionEvent> events = new ArrayList<>();
109+
initializeListeners( events );
110+
111+
EntityA a = new EntityA();
112+
EntityB b = new EntityB();
113+
a.children.add( b );
114+
test( context, getSessionFactory()
115+
.withStatelessTransaction( statelessSession -> statelessSession
116+
.insert( b, a )
117+
.thenCompose( v -> statelessSession.delete( a, b ) )
118+
)
119+
.thenAccept( v -> assertEvents( events ) )
120+
);
121+
}
122+
123+
private static void assertEvents(List<AbstractCollectionEvent> events) {
124+
assertThat( events ).hasSize( 4 );
125+
assertThat( events.get( 0 ) )
126+
.isInstanceOf( PreCollectionRecreateEvent.class )
127+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
128+
assertThat( events.get( 1 ) )
129+
.isInstanceOf( PostCollectionRecreateEvent.class )
130+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
131+
assertThat( events.get( 2 ) )
132+
.isInstanceOf( PreCollectionRemoveEvent.class )
133+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
134+
assertThat( events.get( 3 ) )
135+
.isInstanceOf( PostCollectionRemoveEvent.class )
136+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
137+
}
138+
139+
private void initializeListeners(List<AbstractCollectionEvent> events) {
140+
final EventListenerRegistry registry = ( (SessionFactoryImplementor) factoryManager
141+
.getHibernateSessionFactory() )
142+
.getEventListenerRegistry();
143+
144+
// Clear previous listeners
145+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_RECREATE )
146+
.clearListeners();
147+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_REMOVE )
148+
.clearListeners();
149+
registry.getEventListenerGroup( EventType.POST_COLLECTION_RECREATE )
150+
.clearListeners();
151+
registry.getEventListenerGroup( EventType.POST_COLLECTION_REMOVE )
152+
.clearListeners();
153+
154+
var preRecreate = new MyPreCollectionRecreateEventListener( events );
155+
var preRemove = new MyPreCollectionRemoveEventListener( events );
156+
var postRecreate = new MyPostCollectionRecreateEventListener( events );
157+
var postRemove = new MyPostCollectionRemoveEventListener( events );
158+
159+
// Add new listeners
160+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_RECREATE )
161+
.appendListener( preRecreate );
162+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_REMOVE )
163+
.appendListener( preRemove );
164+
registry.getEventListenerGroup( EventType.POST_COLLECTION_RECREATE )
165+
.appendListener( postRecreate );
166+
registry.getEventListenerGroup( EventType.POST_COLLECTION_REMOVE )
167+
.appendListener( postRemove );
168+
}
169+
170+
@Entity
171+
@Table(name = "ENTITY_A")
172+
public static class EntityA {
173+
174+
@Id
175+
@GeneratedValue(strategy = GenerationType.AUTO)
176+
@Column(name = "ID")
177+
Integer id;
178+
179+
@OneToMany
180+
@JoinColumn(name = "ENTITY_A")
181+
Collection<EntityB> children = new ArrayList<>();
182+
}
183+
184+
@Entity
185+
@Table(name = "ENTITY_B")
186+
public class EntityB {
187+
@Id
188+
@GeneratedValue(strategy = GenerationType.AUTO)
189+
@Column(name = "ID")
190+
Integer id;
191+
}
192+
193+
public static class MyPreCollectionRecreateEventListener implements PreCollectionRecreateEventListener {
194+
195+
private final List<AbstractCollectionEvent> events;
196+
197+
198+
public MyPreCollectionRecreateEventListener(List<AbstractCollectionEvent> events) {
199+
this.events = events;
200+
}
201+
202+
@Override
203+
public void onPreRecreateCollection(PreCollectionRecreateEvent event) {
204+
events.add( event );
205+
}
206+
207+
}
208+
209+
public static class MyPreCollectionRemoveEventListener implements PreCollectionRemoveEventListener {
210+
211+
private final List<AbstractCollectionEvent> events;
212+
213+
public MyPreCollectionRemoveEventListener(List<AbstractCollectionEvent> events) {
214+
this.events = events;
215+
}
216+
217+
@Override
218+
public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
219+
events.add( event );
220+
}
221+
222+
}
223+
224+
public static class MyPostCollectionRecreateEventListener implements PostCollectionRecreateEventListener {
225+
226+
private final List<AbstractCollectionEvent> events;
227+
228+
public MyPostCollectionRecreateEventListener(List<AbstractCollectionEvent> events) {
229+
this.events = events;
230+
}
231+
232+
@Override
233+
public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
234+
events.add( event );
235+
}
236+
}
237+
238+
public static class MyPostCollectionRemoveEventListener implements PostCollectionRemoveEventListener {
239+
240+
private final List<AbstractCollectionEvent> events;
241+
242+
public MyPostCollectionRemoveEventListener(List<AbstractCollectionEvent> events) {
243+
this.events = events;
244+
}
245+
246+
@Override
247+
public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
248+
events.add( event );
249+
}
250+
}
251+
}

0 commit comments

Comments
 (0)