Skip to content

Commit b780bc3

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

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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+
@Test
51+
public void mutinyStatelessInsert(VertxTestContext context) {
52+
final List<AbstractCollectionEvent> events = new ArrayList<>();
53+
initializeListeners( events );
54+
55+
EntityA a = new EntityA();
56+
EntityB b = new EntityB();
57+
a.children.add( b );
58+
test( context, getMutinySessionFactory()
59+
.withStatelessTransaction( statelessSession -> statelessSession
60+
.insert( b )
61+
.chain( () -> statelessSession.insert( a ) )
62+
.chain( () -> statelessSession.delete( a ) )
63+
.chain( () -> statelessSession.delete( b ) )
64+
)
65+
.invoke( () -> assertEvents( events ) )
66+
);
67+
}
68+
69+
@Test
70+
public void mutinyStatelessInsertAll(VertxTestContext context) {
71+
final List<AbstractCollectionEvent> events = new ArrayList<>();
72+
initializeListeners( events );
73+
74+
EntityA a = new EntityA();
75+
EntityB b = new EntityB();
76+
a.children.add( b );
77+
test( context, getMutinySessionFactory()
78+
.withStatelessTransaction( statelessSession -> statelessSession
79+
.insertAll( b, a )
80+
.chain( () -> statelessSession.deleteAll( a, b ) )
81+
)
82+
.invoke( () -> assertEvents( events ) )
83+
);
84+
}
85+
86+
@Test
87+
public void stageStatelessInsert(VertxTestContext context) {
88+
final List<AbstractCollectionEvent> events = new ArrayList<>();
89+
initializeListeners( events );
90+
91+
EntityA a = new EntityA();
92+
EntityB b = new EntityB();
93+
a.children.add( b );
94+
test( context, getSessionFactory()
95+
.withStatelessTransaction( statelessSession -> statelessSession
96+
.insert( b )
97+
.thenCompose( v -> statelessSession.insert( a ) )
98+
.thenCompose( v -> statelessSession.delete( a ) )
99+
.thenCompose( v -> statelessSession.delete( b ) )
100+
)
101+
.thenAccept( v -> assertEvents( events ) )
102+
);
103+
}
104+
105+
@Test
106+
public void stageStatelessInsertAll(VertxTestContext context) {
107+
final List<AbstractCollectionEvent> events = new ArrayList<>();
108+
initializeListeners( events );
109+
110+
EntityA a = new EntityA();
111+
EntityB b = new EntityB();
112+
a.children.add( b );
113+
test( context, getSessionFactory()
114+
.withStatelessTransaction( statelessSession -> statelessSession
115+
.insert( b, a )
116+
.thenCompose( v -> statelessSession.delete( a, b ) )
117+
)
118+
.thenAccept( v -> assertEvents( events ) )
119+
);
120+
}
121+
122+
private static void assertEvents(List<AbstractCollectionEvent> events) {
123+
assertThat( events ).hasSize( 4 );
124+
assertThat( events.get( 0 ) )
125+
.isInstanceOf( PreCollectionRecreateEvent.class )
126+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
127+
assertThat( events.get( 1 ) )
128+
.isInstanceOf( PostCollectionRecreateEvent.class )
129+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
130+
assertThat( events.get( 2 ) )
131+
.isInstanceOf( PreCollectionRemoveEvent.class )
132+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
133+
assertThat( events.get( 3 ) )
134+
.isInstanceOf( PostCollectionRemoveEvent.class )
135+
.extracting( AbstractCollectionEvent::getAffectedOwnerEntityName ).isEqualTo( EntityA.class.getName() );
136+
}
137+
138+
private void initializeListeners(List<AbstractCollectionEvent> events) {
139+
final EventListenerRegistry registry = ( (SessionFactoryImplementor) factoryManager
140+
.getHibernateSessionFactory() )
141+
.getEventListenerRegistry();
142+
143+
// Clear previous listeners
144+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_RECREATE )
145+
.clearListeners();
146+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_REMOVE )
147+
.clearListeners();
148+
registry.getEventListenerGroup( EventType.POST_COLLECTION_RECREATE )
149+
.clearListeners();
150+
registry.getEventListenerGroup( EventType.POST_COLLECTION_REMOVE )
151+
.clearListeners();
152+
153+
var preRecreate = new MyPreCollectionRecreateEventListener( events );
154+
var preRemove = new MyPreCollectionRemoveEventListener( events );
155+
var postRecreate = new MyPostCollectionRecreateEventListener( events );
156+
var postRemove = new MyPostCollectionRemoveEventListener( events );
157+
158+
// Add new listeners
159+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_RECREATE )
160+
.appendListener( preRecreate );
161+
registry.getEventListenerGroup( EventType.PRE_COLLECTION_REMOVE )
162+
.appendListener( preRemove );
163+
registry.getEventListenerGroup( EventType.POST_COLLECTION_RECREATE )
164+
.appendListener( postRecreate );
165+
registry.getEventListenerGroup( EventType.POST_COLLECTION_REMOVE )
166+
.appendListener( postRemove );
167+
}
168+
169+
@Entity
170+
@Table(name = "ENTITY_A")
171+
public static class EntityA {
172+
173+
@Id
174+
@GeneratedValue(strategy = GenerationType.AUTO)
175+
@Column(name = "ID")
176+
Integer id;
177+
178+
@OneToMany
179+
@JoinColumn(name = "ENTITY_A")
180+
Collection<EntityB> children = new ArrayList<>();
181+
}
182+
183+
@Entity
184+
@Table(name = "ENTITY_B")
185+
public class EntityB {
186+
@Id
187+
@GeneratedValue(strategy = GenerationType.AUTO)
188+
@Column(name = "ID")
189+
Integer id;
190+
}
191+
192+
public static class MyPreCollectionRecreateEventListener implements PreCollectionRecreateEventListener {
193+
194+
private final List<AbstractCollectionEvent> events;
195+
196+
197+
public MyPreCollectionRecreateEventListener(List<AbstractCollectionEvent> events) {
198+
this.events = events;
199+
}
200+
201+
@Override
202+
public void onPreRecreateCollection(PreCollectionRecreateEvent event) {
203+
events.add( event );
204+
}
205+
206+
}
207+
208+
public static class MyPreCollectionRemoveEventListener implements PreCollectionRemoveEventListener {
209+
210+
private final List<AbstractCollectionEvent> events;
211+
212+
public MyPreCollectionRemoveEventListener(List<AbstractCollectionEvent> events) {
213+
this.events = events;
214+
}
215+
216+
@Override
217+
public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
218+
events.add( event );
219+
}
220+
221+
}
222+
223+
public static class MyPostCollectionRecreateEventListener implements PostCollectionRecreateEventListener {
224+
225+
private final List<AbstractCollectionEvent> events;
226+
227+
public MyPostCollectionRecreateEventListener(List<AbstractCollectionEvent> events) {
228+
this.events = events;
229+
}
230+
231+
@Override
232+
public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
233+
events.add( event );
234+
}
235+
}
236+
237+
public static class MyPostCollectionRemoveEventListener implements PostCollectionRemoveEventListener {
238+
239+
private final List<AbstractCollectionEvent> events;
240+
241+
public MyPostCollectionRemoveEventListener(List<AbstractCollectionEvent> events) {
242+
this.events = events;
243+
}
244+
245+
@Override
246+
public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
247+
events.add( event );
248+
}
249+
}
250+
}

0 commit comments

Comments
 (0)