Skip to content

Commit e2ca0e7

Browse files
committed
[#1787] added tests for @softdelete
1 parent 9089e5b commit e2ca0e7

File tree

2 files changed

+524
-0
lines changed

2 files changed

+524
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
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.Collection;
9+
import java.util.List;
10+
11+
import org.hibernate.annotations.SoftDelete;
12+
import org.hibernate.annotations.SoftDeleteType;
13+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
14+
import org.hibernate.cfg.Configuration;
15+
import org.hibernate.reactive.testing.SqlStatementTracker;
16+
import org.hibernate.type.NumericBooleanConverter;
17+
import org.hibernate.type.TrueFalseConverter;
18+
import org.hibernate.type.YesNoConverter;
19+
20+
import org.junit.jupiter.api.Test;
21+
22+
import io.vertx.junit5.VertxTestContext;
23+
import jakarta.persistence.Column;
24+
import jakarta.persistence.Entity;
25+
import jakarta.persistence.Id;
26+
import jakarta.persistence.Table;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.junit.jupiter.api.Assertions.assertEquals;
30+
31+
/*
32+
* Tests validity of @SoftDelete annotation value options
33+
*
34+
* @see org.hibernate.annotations.SoftDelete
35+
* @see org.hibernate.orm.test.softdelete.MappingTest
36+
*/
37+
38+
public class SoftDeleteMappingTest extends BaseReactiveTest {
39+
private static SqlStatementTracker sqlTracker;
40+
41+
@Override
42+
protected Configuration constructConfiguration() {
43+
Configuration configuration = super.constructConfiguration();
44+
sqlTracker = new SqlStatementTracker( SoftDeleteMappingTest::filter, configuration.getProperties() );
45+
return configuration;
46+
}
47+
48+
@Override
49+
protected void addServices(StandardServiceRegistryBuilder builder) {
50+
sqlTracker.registerService( builder );
51+
}
52+
53+
protected static boolean filter(String s) {
54+
String[] accepted = {"update "};
55+
for ( String valid : accepted ) {
56+
if ( s.toLowerCase().startsWith( valid ) ) {
57+
return true;
58+
}
59+
}
60+
return false;
61+
}
62+
63+
@Override
64+
protected Collection<Class<?>> annotatedEntities() {
65+
return List.of(
66+
BooleanEntity.class,
67+
NumericEntity.class,
68+
YesNoEntity.class,
69+
TrueFalseEntity.class,
70+
ReversedYesNoEntity.class,
71+
MappedColumnEntity.class
72+
);
73+
}
74+
75+
@Test
76+
public void testBooleanEntity(VertxTestContext context) {
77+
BooleanEntity e1 = new BooleanEntity( 1, "first" );
78+
BooleanEntity e2 = new BooleanEntity( 2, "second" );
79+
BooleanEntity e3 = new BooleanEntity( 3, "third" );
80+
81+
test( context, getSessionFactory()
82+
.withTransaction( session -> session.persist( e1, e2, e3 )
83+
.thenCompose( v -> session.flush() )
84+
).thenCompose( v -> openSession()
85+
.thenCompose( session ->
86+
session.createMutationQuery( "update BooleanEntity set name = null where id = 1" )
87+
.executeUpdate()
88+
.thenCompose( ignore -> session.flush() )
89+
.thenCompose( v1 -> getSessionFactory().withSession(
90+
s -> s.createQuery( "from BooleanEntity where id = 1", BooleanEntity.class ).getSingleResult()
91+
.thenAccept( result -> {
92+
assertEquals( null, result.name );
93+
assertUpdateQueryForEntity( "boolean_entity" );
94+
} ) ) ) ) )
95+
);
96+
}
97+
98+
@Test
99+
public void testNumericEntity(VertxTestContext context) {
100+
NumericEntity e1 = new NumericEntity( 1, "first" );
101+
NumericEntity e2 = new NumericEntity( 2, "second" );
102+
NumericEntity e3 = new NumericEntity( 3, "third" );
103+
104+
test( context, getSessionFactory()
105+
.withTransaction( session -> session.persist( e1, e2, e3 )
106+
.thenCompose( v -> session.flush() )
107+
).thenCompose( v -> openSession()
108+
.thenCompose( session ->
109+
session.createMutationQuery( "update NumericEntity set name = null where id = 1" )
110+
.executeUpdate()
111+
.thenCompose( ignore -> session.flush() )
112+
.thenCompose( v1 -> getSessionFactory().withSession(
113+
s -> s.createQuery( "from NumericEntity where id = 1", NumericEntity.class ).getSingleResult()
114+
.thenAccept( result -> {
115+
assertEquals( null, result.name );
116+
assertUpdateQueryForEntity( "numeric_entity" );
117+
} ) ) ) ) )
118+
);
119+
}
120+
121+
@Test
122+
public void testTrueFalseEntity(VertxTestContext context) {
123+
TrueFalseEntity e1 = new TrueFalseEntity( 1, "first" );
124+
TrueFalseEntity e2 = new TrueFalseEntity( 2, "second" );
125+
TrueFalseEntity e3 = new TrueFalseEntity( 3, "third" );
126+
127+
test( context, getSessionFactory()
128+
.withTransaction( session -> session.persist( e1, e2, e3 )
129+
.thenCompose( v -> session.flush() )
130+
).thenCompose( v -> openSession()
131+
.thenCompose( session ->
132+
session.createMutationQuery( "update TrueFalseEntity set name = null where id = 1" )
133+
.executeUpdate()
134+
.thenCompose( ignore -> session.flush() )
135+
.thenCompose( v1 -> getSessionFactory().withSession(
136+
s -> s.createQuery( "from TrueFalseEntity where id = 1", TrueFalseEntity.class ).getSingleResult()
137+
.thenAccept( result -> {
138+
assertEquals( null, result.name );
139+
assertUpdateQueryForEntity( "true_false_entity" );
140+
} ) ) ) ) )
141+
);
142+
}
143+
144+
@Test
145+
public void testYesNoEntity(VertxTestContext context) {
146+
YesNoEntity e1 = new YesNoEntity( 1, "first" );
147+
YesNoEntity e2 = new YesNoEntity( 2, "second" );
148+
YesNoEntity e3 = new YesNoEntity( 3, "third" );
149+
150+
test( context, getSessionFactory()
151+
.withTransaction( session -> session.persist( e1, e2, e3 )
152+
.thenCompose( v -> session.flush() )
153+
).thenCompose( v -> openSession()
154+
.thenCompose( session ->
155+
session.createMutationQuery( "update YesNoEntity set name = null where id = 1" )
156+
.executeUpdate()
157+
.thenCompose( ignore -> session.flush() )
158+
.thenCompose( v1 -> getSessionFactory().withSession(
159+
s -> s.createQuery( "from YesNoEntity where id = 1", YesNoEntity.class ).getSingleResult()
160+
.thenAccept( result -> {
161+
assertEquals( null, result.name );
162+
assertUpdateQueryForEntity( "yes_no_entity" );
163+
} ) ) ) ) )
164+
);
165+
}
166+
167+
@Test
168+
public void testReversedYesNoEntity(VertxTestContext context) {
169+
ReversedYesNoEntity e1 = new ReversedYesNoEntity( 1, "first" );
170+
ReversedYesNoEntity e2 = new ReversedYesNoEntity( 2, "second" );
171+
ReversedYesNoEntity e3 = new ReversedYesNoEntity( 3, "third" );
172+
173+
test( context, getSessionFactory()
174+
.withTransaction( session -> session.persist( e1, e2, e3 )
175+
.thenCompose( v -> session.flush() )
176+
).thenCompose( v -> openSession()
177+
.thenCompose( session ->
178+
session.createMutationQuery(
179+
"update ReversedYesNoEntity set name = null where id = 1" )
180+
.executeUpdate()
181+
.thenCompose( ignore -> session.flush() )
182+
.thenCompose( v1 -> getSessionFactory().withSession(
183+
s -> s.createQuery( "from ReversedYesNoEntity where id = 1", ReversedYesNoEntity.class ).getSingleResult()
184+
.thenAccept( result -> {
185+
assertEquals( null, result.name );
186+
assertUpdateQueryForEntity(
187+
"reversed_yes_no_entity" );
188+
} ) ) ) ) )
189+
);
190+
}
191+
192+
@Test
193+
public void testMappedColumnEntity(VertxTestContext context) {
194+
195+
MappedColumnEntity e1 = new MappedColumnEntity( 1, "first" );
196+
MappedColumnEntity e2 = new MappedColumnEntity( 2, "second" );
197+
MappedColumnEntity e3 = new MappedColumnEntity( 3, "third" );
198+
199+
test( context, getSessionFactory()
200+
.withTransaction( session -> session.persist( e1, e2, e3 )
201+
.thenCompose( v -> session.flush() )
202+
).thenCompose( v -> openSession()
203+
.thenCompose( session ->
204+
session.createMutationQuery( "update MappedColumnEntity set name = null where id = 1" )
205+
.executeUpdate()
206+
.thenCompose( ignore -> session.flush() )
207+
.thenCompose( vv -> getSessionFactory().withSession(
208+
s -> s.createQuery( "from MappedColumnEntity where id = 1", MappedColumnEntity.class ).getSingleResult()
209+
.thenAccept( result -> assertEquals( null, result.getName() ) ) ) ) ) )
210+
);
211+
}
212+
213+
private void assertUpdateQueryForEntity(String entityName) {
214+
for( String loggedQuery : sqlTracker.getLoggedQueries() ) {
215+
if( loggedQuery.startsWith( "update " + entityName ) ){
216+
return;
217+
}
218+
}
219+
// If logged queries don't contain expected entity type force an assertion check
220+
assertThat( sqlTracker.getLoggedQueries() ).contains( "update " + entityName + " ...." );
221+
}
222+
223+
224+
@Entity(name="BooleanEntity")
225+
@Table(name="boolean_entity")
226+
@SoftDelete()
227+
public static class BooleanEntity {
228+
@Id
229+
private Integer id;
230+
private String name;
231+
232+
public BooleanEntity() {
233+
}
234+
235+
public BooleanEntity(Integer id, String name) {
236+
this.id = id;
237+
this.name = name;
238+
}
239+
}
240+
241+
@Entity(name="NumericEntity")
242+
@Table(name="numeric_entity")
243+
@SoftDelete(converter = NumericBooleanConverter.class)
244+
public static class NumericEntity {
245+
@Id
246+
private Integer id;
247+
private String name;
248+
249+
public NumericEntity() {
250+
}
251+
252+
public NumericEntity(Integer id, String name) {
253+
this.id = id;
254+
this.name = name;
255+
}
256+
}
257+
258+
@Entity(name="TrueFalseEntity")
259+
@Table(name="true_false_entity")
260+
@SoftDelete(converter = TrueFalseConverter.class)
261+
public static class TrueFalseEntity {
262+
@Id
263+
private Integer id;
264+
private String name;
265+
266+
public TrueFalseEntity() {
267+
}
268+
269+
public TrueFalseEntity(Integer id, String name) {
270+
this.id = id;
271+
this.name = name;
272+
}
273+
}
274+
275+
@Entity(name="YesNoEntity")
276+
@Table(name="yes_no_entity")
277+
@SoftDelete(converter = YesNoConverter.class)
278+
public static class YesNoEntity {
279+
@Id
280+
private Integer id;
281+
private String name;
282+
283+
public YesNoEntity() {
284+
}
285+
286+
public YesNoEntity(Integer id, String name) {
287+
this.id = id;
288+
this.name = name;
289+
}
290+
}
291+
292+
@Entity(name="ReversedYesNoEntity")
293+
@Table(name="reversed_yes_no_entity")
294+
@SoftDelete(converter = YesNoConverter.class, strategy = SoftDeleteType.ACTIVE)
295+
public static class ReversedYesNoEntity {
296+
@Id
297+
private Integer id;
298+
private String name;
299+
300+
public ReversedYesNoEntity() {
301+
}
302+
303+
public ReversedYesNoEntity(Integer id, String name) {
304+
this.id = id;
305+
this.name = name;
306+
}
307+
}
308+
309+
310+
@Entity( name = "MappedColumnEntity" )
311+
@SoftDelete( columnName = "is_deleted" )
312+
public static class MappedColumnEntity {
313+
@Id
314+
private Integer id;
315+
316+
private String name;
317+
318+
// Note that this column's name is the same as the @SoftDelete columnName.
319+
// ORM Treats them different as long as the additional value parameters are used
320+
@Column( name = "is_deleted", insertable = false, updatable = false )
321+
private boolean deleted;
322+
323+
public MappedColumnEntity() {
324+
}
325+
326+
public MappedColumnEntity(Integer id, String name) {
327+
this.id = id;
328+
this.name = name;
329+
}
330+
331+
public Integer getId() {
332+
return id;
333+
}
334+
335+
public String getName() {
336+
return name;
337+
}
338+
339+
public boolean isDeleted() {
340+
return deleted;
341+
}
342+
}
343+
}

0 commit comments

Comments
 (0)