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