5
5
import java .time .Instant ;
6
6
import java .util .ArrayList ;
7
7
import java .util .List ;
8
+ import java .util .Map ;
8
9
import javax .persistence .Column ;
9
10
import javax .persistence .Entity ;
10
11
import javax .persistence .EntityManager ;
19
20
import javax .persistence .criteria .CriteriaBuilder ;
20
21
import javax .persistence .criteria .CriteriaQuery ;
21
22
22
- import org .hibernate .engine .internal .StatefulPersistenceContext ;
23
- import org .hibernate .engine .spi .CollectionKey ;
23
+ import org .hibernate .cfg .AvailableSettings ;
24
24
import org .hibernate .jpa .test .BaseEntityManagerFunctionalTestCase ;
25
+ import org .hibernate .loader .BatchFetchStyle ;
25
26
26
- import org .junit .Ignore ;
27
27
import org .junit .Test ;
28
28
29
29
import static org .hibernate .testing .transaction .TransactionUtil .doInJPA ;
30
+ import static org .junit .Assert .assertFalse ;
30
31
import static org .junit .Assert .assertNotNull ;
31
32
32
- @ Ignore ("Manual performance test" )
33
33
public class CriteriaPerformanceTest extends BaseEntityManagerFunctionalTestCase {
34
34
35
35
@ Override
36
36
public Class [] getAnnotatedClasses () {
37
37
return new Class [] {
38
38
CriteriaPerformanceTest .Author .class ,
39
- CriteriaPerformanceTest .Book .class ,
40
- CriteriaPerformanceTest .Other .class
39
+ CriteriaPerformanceTest .Book .class
41
40
};
42
41
}
43
42
44
- /**
45
- * This test demonstrates that fetching entities with associations fires expensive initializers in 6.1 even
46
- * if the entities are already present in the 1LC.
47
- * <p>
48
- * To verify this behavior, set a breakpoint in {@link StatefulPersistenceContext#getCollection(CollectionKey)}.
49
- * In 6.1, breakpoint will be hit for every collection of books associated with each author.
50
- * In 5.6, breakpoint will never be hit.
51
- */
52
- @ Test
53
- public void testFetchEntityWithAssociations () {
54
- doInJPA ( this ::entityManagerFactory , entityManager -> {
55
- for ( int i = 0 ; i < 1000 ; i ++ ) {
56
- populateData ( entityManager );
57
- }
58
-
59
- final CriteriaBuilder builder = entityManager .getCriteriaBuilder ();
60
- final CriteriaQuery <Author > query = builder .createQuery ( Author .class );
61
- query .from ( Author .class );
62
-
63
- final List <Author > author = entityManager .createQuery ( query ).getResultList ();
64
- assertNotNull ( author );
65
- } );
43
+ @ Override
44
+ protected void addConfigOptions (Map options ) {
45
+ options .put ( AvailableSettings .BATCH_FETCH_STYLE , BatchFetchStyle .DYNAMIC );
46
+ options .put ( AvailableSettings .DEFAULT_BATCH_FETCH_SIZE , 10 );
66
47
}
67
48
68
- /**
69
- * This test demonstrates the difference in performance for a simple criteria query between 5.6 and 6.1.
70
- * (5.6 is about 30% faster on my machine)
71
- * <p>
72
- * The difference in performance seems to have two main causes:
73
- * <p>
74
- * 1. Elevated access to the persistence context as demonstrated by the test above
75
- * 2. Missing query plan cache for criteria queries (possibly)
76
- */
77
49
@ Test
78
50
public void testFetchEntityWithAssociationsPerformance () {
79
51
doInJPA ( this ::entityManagerFactory , entityManager -> {
80
52
for ( int i = 0 ; i < 1000 ; i ++ ) {
81
53
populateData ( entityManager );
82
54
}
83
-
55
+ } );
56
+ doInJPA ( this ::entityManagerFactory , entityManager -> {
84
57
final Instant startTime = Instant .now ();
85
58
86
59
for ( int i = 0 ; i < 100_000 ; i ++ ) {
@@ -89,6 +62,7 @@ public void testFetchEntityWithAssociationsPerformance() {
89
62
query .from ( Author .class );
90
63
final List <Author > authors = entityManager .createQuery ( query ).getResultList ();
91
64
assertNotNull ( authors );
65
+ authors .forEach ( author -> assertFalse ( author .books .isEmpty () ) );
92
66
}
93
67
94
68
System .out .println ( MessageFormat .format (
@@ -99,100 +73,6 @@ public void testFetchEntityWithAssociationsPerformance() {
99
73
} );
100
74
}
101
75
102
- /**
103
- * This test demonstrates the difference in performance for a simple criteria query between 5.6 and 6.1.
104
- * (5.6 is about 30% faster on my machine)
105
- * <p>
106
- * The difference in performance seems to have two main causes:
107
- * <p>
108
- * 1. Elevated access to the persistence context as demonstrated by the test above
109
- * 2. Missing query plan cache for criteria queries (possibly)
110
- */
111
- @ Test
112
- public void testFetchEntityPerformance () {
113
- doInJPA ( this ::entityManagerFactory , entityManager -> {
114
- for ( int i = 0 ; i < 1000 ; i ++ ) {
115
- populateSimpleData ( entityManager );
116
- }
117
-
118
- final Instant startTime = Instant .now ();
119
-
120
- for ( int i = 0 ; i < 100_000 ; i ++ ) {
121
- final CriteriaBuilder builder = entityManager .getCriteriaBuilder ();
122
- final CriteriaQuery <Other > query = builder .createQuery ( Other .class );
123
- query .from ( Other .class );
124
- final List <Other > others = entityManager .createQuery ( query ).getResultList ();
125
- assertNotNull ( others );
126
- }
127
-
128
- System .out .println ( MessageFormat .format (
129
- "{0} took {1}" ,
130
- "Simple Query" ,
131
- Duration .between ( startTime , Instant .now () )
132
- ) );
133
- } );
134
- }
135
-
136
- /**
137
- * This test demonstrates the difference in performance for a simple criteria query between 5.6 and 6.1.
138
- * (5.6 is about 5-7% faster on my machine)
139
- */
140
- @ Test
141
- public void testFetchEntityPerformanceSmallTransactions () {
142
- doInJPA ( this ::entityManagerFactory , entityManager -> {
143
- for ( int i = 0 ; i < 1000 ; i ++ ) {
144
- populateSimpleData ( entityManager );
145
- }
146
- } );
147
-
148
- final Instant startTime = Instant .now ();
149
-
150
- for ( int i = 0 ; i < 100_000 ; i ++ ) {
151
- doInJPA ( this ::entityManagerFactory , entityManager -> {
152
- final CriteriaBuilder builder = entityManager .getCriteriaBuilder ();
153
- final CriteriaQuery <Other > query = builder .createQuery ( Other .class );
154
- query .from ( Other .class );
155
- final List <Other > others = entityManager .createQuery ( query ).getResultList ();
156
- assertNotNull ( others );
157
- } );
158
- }
159
-
160
- System .out .println ( MessageFormat .format (
161
- "{0} took {1}" ,
162
- "Simple Query Criteria" ,
163
- Duration .between ( startTime , Instant .now () )
164
- ) );
165
- }
166
-
167
- /**
168
- * This test demonstrates the difference in performance for a simple HQL query between 5.6 and 6.1.
169
- * (5.6 is about 5-7% faster on my machine)
170
- */
171
- @ Test
172
- public void testFetchEntityPerformanceSmallTransactionsHql () {
173
- doInJPA ( this ::entityManagerFactory , entityManager -> {
174
- for ( int i = 0 ; i < 1000 ; i ++ ) {
175
- populateSimpleData ( entityManager );
176
- }
177
- } );
178
-
179
- final Instant startTime = Instant .now ();
180
-
181
- for ( int i = 0 ; i < 100_000 ; i ++ ) {
182
- doInJPA ( this ::entityManagerFactory , entityManager -> {
183
- final List <Other > others = entityManager .createQuery ( "SELECT p FROM Other p" , Other .class )
184
- .getResultList ();
185
- assertNotNull ( others );
186
- } );
187
- }
188
-
189
- System .out .println ( MessageFormat .format (
190
- "{0} took {1}" ,
191
- "Simple Query HQL" ,
192
- Duration .between ( startTime , Instant .now () )
193
- ) );
194
- }
195
-
196
76
public void populateData (EntityManager entityManager ) {
197
77
final Book book = new Book ();
198
78
book .name = "HTTP Definitive guide" ;
@@ -204,13 +84,7 @@ public void populateData(EntityManager entityManager) {
204
84
book .author = author ;
205
85
206
86
entityManager .persist ( author );
207
- }
208
-
209
- public void populateSimpleData (EntityManager entityManager ) {
210
- final Other other = new Other ();
211
- other .name = "Other" ;
212
-
213
- entityManager .persist ( other );
87
+ entityManager .persist ( book );
214
88
}
215
89
216
90
@ Entity (name = "Author" )
@@ -241,15 +115,4 @@ public static class Book {
241
115
@ JoinColumn (name = "author_id" , nullable = false )
242
116
public Author author ;
243
117
}
244
-
245
- @ Entity (name = "Other" )
246
- @ Table (name = "Other" )
247
- public static class Other {
248
- @ Id
249
- @ GeneratedValue (strategy = GenerationType .IDENTITY )
250
- public Long otherId ;
251
-
252
- @ Column
253
- public String name ;
254
- }
255
118
}
0 commit comments