1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.submitted.cursor_simple;
17
18 import java.io.IOException;
19 import java.io.Reader;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.NoSuchElementException;
24
25 import org.apache.ibatis.BaseDataTest;
26 import org.apache.ibatis.cursor.Cursor;
27 import org.apache.ibatis.io.Resources;
28 import org.apache.ibatis.session.RowBounds;
29 import org.apache.ibatis.session.SqlSession;
30 import org.apache.ibatis.session.SqlSessionFactory;
31 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
32 import org.junit.jupiter.api.Assertions;
33 import org.junit.jupiter.api.BeforeAll;
34 import org.junit.jupiter.api.MethodOrderer;
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.TestMethodOrder;
37
38 @TestMethodOrder(MethodOrderer.MethodName.class)
39 class CursorSimpleTest {
40
41 private static SqlSessionFactory sqlSessionFactory;
42
43 @BeforeAll
44 static void setUp() throws Exception {
45
46 try (
47 Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cursor_simple/mybatis-config.xml")) {
48 sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
49 }
50
51
52 BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
53 "org/apache/ibatis/submitted/cursor_simple/CreateDB.sql");
54 }
55
56 @Test
57 void shouldGetAllUser() {
58 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
59 Mapper mapper = sqlSession.getMapper(Mapper.class);
60 Cursor<User> usersCursor = mapper.getAllUsers();
61
62 Assertions.assertFalse(usersCursor.isOpen());
63
64
65 Assertions.assertEquals(-1, usersCursor.getCurrentIndex());
66
67 Iterator<User> iterator = usersCursor.iterator();
68
69
70 Assertions.assertTrue(iterator.hasNext());
71 Assertions.assertTrue(usersCursor.isOpen());
72 Assertions.assertFalse(usersCursor.isConsumed());
73
74
75 Assertions.assertEquals(-1, usersCursor.getCurrentIndex());
76
77 User user = iterator.next();
78 Assertions.assertEquals("User1", user.getName());
79 Assertions.assertEquals(0, usersCursor.getCurrentIndex());
80
81 user = iterator.next();
82 Assertions.assertEquals("User2", user.getName());
83 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
84
85 user = iterator.next();
86 Assertions.assertEquals("User3", user.getName());
87 Assertions.assertEquals(2, usersCursor.getCurrentIndex());
88
89 user = iterator.next();
90 Assertions.assertEquals("User4", user.getName());
91 Assertions.assertEquals(3, usersCursor.getCurrentIndex());
92
93 user = iterator.next();
94 Assertions.assertEquals("User5", user.getName());
95 Assertions.assertEquals(4, usersCursor.getCurrentIndex());
96
97
98 Assertions.assertFalse(iterator.hasNext());
99 Assertions.assertFalse(usersCursor.isOpen());
100 Assertions.assertTrue(usersCursor.isConsumed());
101 }
102 }
103
104 @Test
105 void cursorClosedOnSessionClose() {
106 Cursor<User> usersCursor;
107 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
108 Mapper mapper = sqlSession.getMapper(Mapper.class);
109 usersCursor = mapper.getAllUsers();
110
111 Assertions.assertFalse(usersCursor.isOpen());
112
113 Iterator<User> iterator = usersCursor.iterator();
114
115
116 Assertions.assertTrue(iterator.hasNext());
117 Assertions.assertTrue(usersCursor.isOpen());
118 Assertions.assertFalse(usersCursor.isConsumed());
119
120
121 User user = iterator.next();
122 Assertions.assertEquals("User1", user.getName());
123
124
125 Assertions.assertTrue(iterator.hasNext());
126 Assertions.assertTrue(usersCursor.isOpen());
127 Assertions.assertFalse(usersCursor.isConsumed());
128 }
129
130
131 Assertions.assertFalse(usersCursor.isOpen());
132 Assertions.assertFalse(usersCursor.isConsumed());
133 }
134
135 @Test
136 void cursorWithRowBound() {
137 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
138
139 Cursor<User> usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 3));
140
141 Iterator<User> iterator = usersCursor.iterator();
142
143 User user = iterator.next();
144 Assertions.assertEquals("User2", user.getName());
145 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
146
147
148 Assertions.assertTrue(iterator.hasNext());
149 user = iterator.next();
150 Assertions.assertEquals("User3", user.getName());
151 Assertions.assertEquals(2, usersCursor.getCurrentIndex());
152
153
154 user = iterator.next();
155 Assertions.assertEquals("User4", user.getName());
156 Assertions.assertEquals(3, usersCursor.getCurrentIndex());
157
158 Assertions.assertFalse(iterator.hasNext());
159 Assertions.assertFalse(usersCursor.isOpen());
160 Assertions.assertTrue(usersCursor.isConsumed());
161 }
162 }
163
164 @Test
165 void cursorIteratorNoSuchElementExceptionWithHasNext() throws IOException {
166 try (SqlSession sqlSession = sqlSessionFactory.openSession();
167 Cursor<User> usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) {
168 try {
169 Iterator<User> iterator = usersCursor.iterator();
170
171 User user = iterator.next();
172 Assertions.assertEquals("User2", user.getName());
173 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
174
175 Assertions.assertFalse(iterator.hasNext());
176 iterator.next();
177 Assertions.fail("We should have failed since we call next() when hasNext() returned false");
178 } catch (NoSuchElementException e) {
179 Assertions.assertFalse(usersCursor.isOpen());
180 Assertions.assertTrue(usersCursor.isConsumed());
181 }
182 }
183 }
184
185 @Test
186 void cursorIteratorNoSuchElementExceptionNoHasNext() throws IOException {
187 try (SqlSession sqlSession = sqlSessionFactory.openSession();
188 Cursor<User> usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) {
189 try {
190 Iterator<User> iterator = usersCursor.iterator();
191 User user = iterator.next();
192 Assertions.assertEquals("User2", user.getName());
193 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
194
195
196 iterator.next();
197 Assertions.fail("We should have failed since we call next() when is no more items");
198 } catch (NoSuchElementException e) {
199 Assertions.assertFalse(usersCursor.isOpen());
200 Assertions.assertTrue(usersCursor.isConsumed());
201 }
202 }
203 }
204
205 @Test
206 void cursorWithBadRowBound() {
207 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
208
209 Cursor<User> usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(10, 2));
210 Iterator<User> iterator = usersCursor.iterator();
211
212 Assertions.assertFalse(iterator.hasNext());
213 Assertions.assertFalse(usersCursor.isOpen());
214 Assertions.assertTrue(usersCursor.isConsumed());
215 }
216 }
217
218 @Test
219 void cursorMultipleHasNextCall() {
220 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
221 Mapper mapper = sqlSession.getMapper(Mapper.class);
222 Cursor<User> usersCursor = mapper.getAllUsers();
223
224 Iterator<User> iterator = usersCursor.iterator();
225
226 Assertions.assertEquals(-1, usersCursor.getCurrentIndex());
227
228 User user = iterator.next();
229 Assertions.assertEquals("User1", user.getName());
230 Assertions.assertEquals(0, usersCursor.getCurrentIndex());
231
232 Assertions.assertTrue(iterator.hasNext());
233 Assertions.assertTrue(iterator.hasNext());
234 Assertions.assertTrue(iterator.hasNext());
235
236 Assertions.assertEquals(0, usersCursor.getCurrentIndex());
237 }
238 }
239
240 @Test
241 void cursorMultipleIteratorCall() {
242 Iterator<User> iterator2 = null;
243 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
244 Mapper mapper = sqlSession.getMapper(Mapper.class);
245 Cursor<User> usersCursor = mapper.getAllUsers();
246
247 Iterator<User> iterator = usersCursor.iterator();
248 User user = iterator.next();
249 Assertions.assertEquals("User1", user.getName());
250 Assertions.assertEquals(0, usersCursor.getCurrentIndex());
251
252 iterator2 = usersCursor.iterator();
253 iterator2.hasNext();
254 Assertions.fail("We should have failed since calling iterator several times is not allowed");
255 } catch (IllegalStateException e) {
256 Assertions.assertNull(iterator2, "iterator2 should be null");
257 return;
258 }
259 Assertions.fail("Should have returned earlier");
260 }
261
262 @Test
263 void cursorMultipleCloseCall() throws IOException {
264 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
265 Mapper mapper = sqlSession.getMapper(Mapper.class);
266 Cursor<User> usersCursor = mapper.getAllUsers();
267
268 Assertions.assertFalse(usersCursor.isOpen());
269
270 Iterator<User> iterator = usersCursor.iterator();
271
272
273 Assertions.assertTrue(iterator.hasNext());
274 Assertions.assertTrue(usersCursor.isOpen());
275 Assertions.assertFalse(usersCursor.isConsumed());
276
277
278 User user = iterator.next();
279 Assertions.assertEquals("User1", user.getName());
280
281 usersCursor.close();
282
283 usersCursor.close();
284
285
286 Assertions.assertFalse(iterator.hasNext());
287 Assertions.assertFalse(usersCursor.isOpen());
288 Assertions.assertFalse(usersCursor.isConsumed());
289 }
290 }
291
292 @Test
293 void cursorUsageAfterClose() throws IOException {
294
295 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
296 Mapper mapper = sqlSession.getMapper(Mapper.class);
297
298 Cursor<User> usersCursor = mapper.getAllUsers();
299 try {
300 Iterator<User> iterator = usersCursor.iterator();
301 User user = iterator.next();
302 Assertions.assertEquals("User1", user.getName());
303 Assertions.assertEquals(0, usersCursor.getCurrentIndex());
304
305 user = iterator.next();
306 Assertions.assertEquals("User2", user.getName());
307 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
308
309 usersCursor.close();
310
311
312 Assertions.assertFalse(iterator.hasNext());
313 Assertions.assertFalse(usersCursor.isOpen());
314 Assertions.assertFalse(usersCursor.isConsumed());
315
316
317 iterator.next();
318
319 Assertions.fail("We should have failed with NoSuchElementException since Cursor is closed");
320 } catch (NoSuchElementException e) {
321
322 Assertions.assertEquals(1, usersCursor.getCurrentIndex());
323 usersCursor.close();
324 return;
325 }
326 }
327
328 Assertions.fail("Should have returned earlier");
329 }
330
331 @Test
332 void shouldGetAllUserUsingAnnotationBasedMapper() {
333 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
334 sqlSession.getConfiguration().getMapperRegistry().addMapper(AnnotationMapper.class);
335 AnnotationMapper mapper = sqlSession.getMapper(AnnotationMapper.class);
336 Cursor<User> usersCursor = mapper.getAllUsers();
337
338 Assertions.assertFalse(usersCursor.isOpen());
339 Assertions.assertFalse(usersCursor.isConsumed());
340 Assertions.assertEquals(-1, usersCursor.getCurrentIndex());
341
342 List<User> userList = new ArrayList<>();
343 for (User user : usersCursor) {
344 userList.add(user);
345 Assertions.assertEquals(userList.size() - 1, usersCursor.getCurrentIndex());
346 }
347
348 Assertions.assertFalse(usersCursor.isOpen());
349 Assertions.assertTrue(usersCursor.isConsumed());
350 Assertions.assertEquals(4, usersCursor.getCurrentIndex());
351
352 Assertions.assertEquals(5, userList.size());
353 User user = userList.get(0);
354 Assertions.assertEquals("User1", user.getName());
355 user = userList.get(1);
356 Assertions.assertEquals("User2", user.getName());
357 user = userList.get(2);
358 Assertions.assertEquals("User3", user.getName());
359 user = userList.get(3);
360 Assertions.assertEquals("User4", user.getName());
361 user = userList.get(4);
362 Assertions.assertEquals("User5", user.getName());
363 }
364 }
365
366 @Test
367 void shouldThrowIllegalStateExceptionUsingIteratorOnSessionClosed() {
368 Cursor<User> usersCursor;
369 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
370 usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers();
371 }
372 try {
373 usersCursor.iterator();
374 Assertions.fail("Should throws the IllegalStateException when call the iterator method after session is closed.");
375 } catch (IllegalStateException e) {
376 Assertions.assertEquals("A Cursor is already closed.", e.getMessage());
377 }
378
379
380 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
381 usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers();
382 usersCursor.iterator();
383 }
384 try {
385 usersCursor.iterator();
386 Assertions.fail("Should throws the IllegalStateException when call the iterator already.");
387 } catch (IllegalStateException e) {
388 Assertions.assertEquals("Cannot open more than one iterator on a Cursor", e.getMessage());
389 }
390
391 }
392
393 @Test
394 void shouldNullItemNotStopIteration() {
395 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
396 Mapper mapper = sqlSession.getMapper(Mapper.class);
397 Cursor<User> cursor = mapper.getNullUsers(new RowBounds());
398 Iterator<User> iterator = cursor.iterator();
399
400 Assertions.assertFalse(cursor.isOpen());
401
402
403 Assertions.assertEquals(-1, cursor.getCurrentIndex());
404
405
406 Assertions.assertTrue(iterator.hasNext());
407
408 Assertions.assertTrue(iterator.hasNext());
409 Assertions.assertTrue(cursor.isOpen());
410 Assertions.assertFalse(cursor.isConsumed());
411
412
413 Assertions.assertEquals(-1, cursor.getCurrentIndex());
414
415 User user = iterator.next();
416 Assertions.assertNull(user);
417 Assertions.assertEquals(0, cursor.getCurrentIndex());
418
419 Assertions.assertTrue(iterator.hasNext());
420 user = iterator.next();
421 Assertions.assertEquals("Kate", user.getName());
422 Assertions.assertEquals(1, cursor.getCurrentIndex());
423
424 Assertions.assertTrue(iterator.hasNext());
425 user = iterator.next();
426 Assertions.assertNull(user);
427 Assertions.assertEquals(2, cursor.getCurrentIndex());
428
429 Assertions.assertTrue(iterator.hasNext());
430 user = iterator.next();
431 Assertions.assertNull(user);
432 Assertions.assertEquals(3, cursor.getCurrentIndex());
433
434
435 Assertions.assertFalse(iterator.hasNext());
436 Assertions.assertFalse(cursor.isOpen());
437 Assertions.assertTrue(cursor.isConsumed());
438 }
439 }
440
441 @Test
442 void shouldRowBoundsCountNullItem() {
443 try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
444 Mapper mapper = sqlSession.getMapper(Mapper.class);
445 Cursor<User> cursor = mapper.getNullUsers(new RowBounds(1, 2));
446 Iterator<User> iterator = cursor.iterator();
447
448 Assertions.assertFalse(cursor.isOpen());
449
450
451 Assertions.assertTrue(iterator.hasNext());
452
453 Assertions.assertTrue(iterator.hasNext());
454 Assertions.assertTrue(cursor.isOpen());
455 Assertions.assertFalse(cursor.isConsumed());
456
457 User user = iterator.next();
458 Assertions.assertEquals("Kate", user.getName());
459 Assertions.assertEquals(1, cursor.getCurrentIndex());
460
461 Assertions.assertTrue(iterator.hasNext());
462 user = iterator.next();
463 Assertions.assertNull(user);
464 Assertions.assertEquals(2, cursor.getCurrentIndex());
465
466
467 Assertions.assertFalse(iterator.hasNext());
468 Assertions.assertFalse(cursor.isOpen());
469 Assertions.assertTrue(cursor.isConsumed());
470 }
471 }
472 }