Skip to content

Commit 2cfd7f2

Browse files
committed
HHH-19781 Add test for issue
1 parent f9bb185 commit 2cfd7f2

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed

hibernate-core/src/test/java/org/hibernate/orm/test/query/dynamic/BasicEntity.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,36 @@ public class BasicEntity {
2222

2323
@ManyToOne
2424
OtherEntity other;
25+
26+
public Integer getId() {
27+
return id;
28+
}
29+
30+
public void setId(Integer id) {
31+
this.id = id;
32+
}
33+
34+
public String getName() {
35+
return name;
36+
}
37+
38+
public void setName(String name) {
39+
this.name = name;
40+
}
41+
42+
public int getPosition() {
43+
return position;
44+
}
45+
46+
public void setPosition(int position) {
47+
this.position = position;
48+
}
49+
50+
public OtherEntity getOther() {
51+
return other;
52+
}
53+
54+
public void setOther(OtherEntity other) {
55+
this.other = other;
56+
}
2557
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.query.dynamic;
6+
7+
import java.util.function.Consumer;
8+
9+
import org.hibernate.query.Order;
10+
import org.hibernate.query.restriction.Restriction;
11+
import org.hibernate.query.specification.MutationSpecification;
12+
import org.hibernate.query.specification.SelectionSpecification;
13+
14+
import org.hibernate.testing.orm.junit.DomainModel;
15+
import org.hibernate.testing.orm.junit.Jira;
16+
import org.hibernate.testing.orm.junit.SessionFactory;
17+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
18+
import org.junit.jupiter.api.AfterAll;
19+
import org.junit.jupiter.api.BeforeAll;
20+
import org.junit.jupiter.api.Test;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
24+
@DomainModel(annotatedClasses = {
25+
BasicEntity.class,
26+
OtherEntity.class,
27+
})
28+
@SessionFactory(useCollectingStatementInspector = true)
29+
@Jira( "https://hibernate.atlassian.net/browse/HHH-19781" )
30+
public class SpecificationReuseTest {
31+
@Test
32+
public void dynamicSelect(SessionFactoryScope scope) {
33+
final var inspector = scope.getCollectingStatementInspector();
34+
scope.inTransaction( session -> {
35+
final var spec = SelectionSpecification.create( BasicEntity.class )
36+
.sort( Order.asc( BasicEntity_.position ) )
37+
.restrict( Restriction.like( BasicEntity_.name, "entity_%" ) );
38+
nTimes( spec, 3, s -> {
39+
inspector.clear();
40+
assertThat( s.createQuery( session ).list() ).extracting( BasicEntity::getId ).containsExactly( 2, 1 );
41+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "position", 2 );
42+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "name", 2 );
43+
} );
44+
} );
45+
}
46+
47+
@Test
48+
public void hqlSelect(SessionFactoryScope scope) {
49+
final var inspector = scope.getCollectingStatementInspector();
50+
scope.inTransaction( session -> {
51+
final var spec = SelectionSpecification.create( BasicEntity.class, "from BasicEntity" )
52+
.sort( Order.asc( BasicEntity_.position ) )
53+
.restrict( Restriction.like( BasicEntity_.name, "entity_%" ) );
54+
nTimes( spec, 3, s -> {
55+
inspector.clear();
56+
assertThat( s.createQuery( session ).list() ).extracting( BasicEntity::getId ).containsExactly( 2, 1 );
57+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "position", 2 );
58+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "name", 2 );
59+
} );
60+
} );
61+
}
62+
63+
@Test
64+
public void criteriaSelect(SessionFactoryScope scope) {
65+
final var inspector = scope.getCollectingStatementInspector();
66+
scope.inTransaction( session -> {
67+
final var cb = session.getCriteriaBuilder();
68+
final var query = cb.createQuery( BasicEntity.class );
69+
final var root = query.from( BasicEntity.class );
70+
final var spec = SelectionSpecification.create( query.select( root ) )
71+
.sort( Order.asc( BasicEntity_.position ) )
72+
.restrict( Restriction.like( BasicEntity_.name, "entity_%" ) );
73+
nTimes( spec, 3, s -> {
74+
inspector.clear();
75+
assertThat( s.createQuery( session ).list() ).extracting( BasicEntity::getId ).containsExactly( 2, 1 );
76+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "position", 2 );
77+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "name", 2 );
78+
} );
79+
} );
80+
}
81+
82+
@Test
83+
public void hqlMutation(SessionFactoryScope scope) {
84+
final var inspector = scope.getCollectingStatementInspector();
85+
scope.inTransaction( session -> {
86+
final var e = new BasicEntity();
87+
e.setId( 33 );
88+
session.persist( e );
89+
} );
90+
scope.inTransaction( session -> {
91+
final var spec = MutationSpecification.create( BasicEntity.class, "update BasicEntity set name = 'entity_33'" )
92+
.restrict( Restriction.equal( BasicEntity_.id, 33 ) );
93+
nTimes( spec, 3, s -> {
94+
inspector.clear();
95+
assertThat( s.createQuery( session ).executeUpdate() ).isEqualTo( 1 );
96+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "id", 1 );
97+
} );
98+
} );
99+
scope.inTransaction( session -> {
100+
final var spec = MutationSpecification.create( BasicEntity.class, "delete BasicEntity" )
101+
.restrict( Restriction.equal( BasicEntity_.name, "entity_33" ) );
102+
nTimes( spec, 3, s -> {
103+
inspector.clear();
104+
s.createQuery( session ).executeUpdate();
105+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "name", 1 );
106+
} );
107+
} );
108+
}
109+
110+
@Test
111+
public void criteriaMutation(SessionFactoryScope scope) {
112+
final var inspector = scope.getCollectingStatementInspector();
113+
scope.inTransaction( session -> {
114+
final var e = new BasicEntity();
115+
e.setId( 44 );
116+
session.persist( e );
117+
} );
118+
scope.inTransaction( session -> {
119+
final var cb = session.getCriteriaBuilder();
120+
final var cu = cb.createCriteriaUpdate( BasicEntity.class );
121+
final var spec = MutationSpecification.create( cu.set( BasicEntity_.name, "entity_44" ) )
122+
.restrict( Restriction.equal( BasicEntity_.id, 44 ) );
123+
nTimes( spec, 3, s -> {
124+
inspector.clear();
125+
assertThat( s.createQuery( session ).executeUpdate() ).isEqualTo( 1 );
126+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "id", 1 );
127+
} );
128+
} );
129+
scope.inTransaction( session -> {
130+
final var cb = session.getCriteriaBuilder();
131+
final var cd = cb.createCriteriaDelete( BasicEntity.class );
132+
final var spec = MutationSpecification.create( cd )
133+
.restrict( Restriction.equal( BasicEntity_.name, "entity_44" ) );
134+
nTimes( spec, 3, s -> {
135+
inspector.clear();
136+
s.createQuery( session ).executeUpdate();
137+
inspector.assertNumberOfOccurrenceInQueryNoSpace( 0, "name", 1 );
138+
} );
139+
} );
140+
}
141+
142+
<T> void nTimes(SelectionSpecification<T> spec, int n, Consumer<SelectionSpecification<T>> consumer) {
143+
for ( int i = 0; i < n; i++ ) {
144+
consumer.accept( spec );
145+
}
146+
}
147+
148+
<T> void nTimes(MutationSpecification<T> spec, int n, Consumer<MutationSpecification<T>> consumer) {
149+
for ( int i = 0; i < n; i++ ) {
150+
consumer.accept( spec );
151+
}
152+
}
153+
154+
@BeforeAll
155+
public void setUp(SessionFactoryScope scope) {
156+
scope.inTransaction( session -> {
157+
final var e1 = new BasicEntity();
158+
e1.setId( 1 );
159+
e1.setName( "entity_1" );
160+
e1.setPosition( 99 );
161+
session.persist( e1 );
162+
163+
final var e2 = new BasicEntity();
164+
e2.setId( 2 );
165+
e2.setName( "entity_2" );
166+
e2.setPosition( 42 );
167+
session.persist( e2 );
168+
} );
169+
}
170+
171+
@AfterAll
172+
public void tearDown(SessionFactoryScope scope) {
173+
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
174+
}
175+
}

0 commit comments

Comments
 (0)