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