diff --git a/src/main/java/org/apache/ibatis/cursor/defaults/DefaultCursor.java b/src/main/java/org/apache/ibatis/cursor/defaults/DefaultCursor.java index e82a0d09241..a7a92c5aac9 100644 --- a/src/main/java/org/apache/ibatis/cursor/defaults/DefaultCursor.java +++ b/src/main/java/org/apache/ibatis/cursor/defaults/DefaultCursor.java @@ -37,188 +37,188 @@ */ public class DefaultCursor implements Cursor { - // ResultSetHandler stuff - private final DefaultResultSetHandler resultSetHandler; - private final ResultMap resultMap; - private final ResultSetWrapper rsw; - private final RowBounds rowBounds; - private final ObjectWrapperResultHandler objectWrapperResultHandler = new ObjectWrapperResultHandler<>(); - - private final CursorIterator cursorIterator = new CursorIterator(); - private boolean iteratorRetrieved; - - private CursorStatus status = CursorStatus.CREATED; - private int indexWithRowBound = -1; - - private enum CursorStatus { - - /** - * A freshly created cursor, database ResultSet consuming has not started - */ - CREATED, - /** - * A cursor currently in use, database ResultSet consuming has started - */ - OPEN, - /** - * A closed cursor, not fully consumed - */ - CLOSED, - /** - * A fully consumed cursor, a consumed cursor is always closed - */ - CONSUMED + // ResultSetHandler stuff + private final DefaultResultSetHandler resultSetHandler; + private final ResultMap resultMap; + private final ResultSetWrapper rsw; + private final RowBounds rowBounds; + private final ObjectWrapperResultHandler objectWrapperResultHandler = new ObjectWrapperResultHandler<>(); + + private final CursorIterator cursorIterator = new CursorIterator(); + private boolean iteratorRetrieved; + + private CursorStatus status = CursorStatus.CREATED; + private int indexWithRowBound = -1; + + private enum CursorStatus { + + /** + * A freshly created cursor, database ResultSet consuming has not started + */ + CREATED, + /** + * A cursor currently in use, database ResultSet consuming has started + */ + OPEN, + /** + * A closed cursor, not fully consumed + */ + CLOSED, + /** + * A fully consumed cursor, a consumed cursor is always closed + */ + CONSUMED + } + + public DefaultCursor(DefaultResultSetHandler resultSetHandler, ResultMap resultMap, ResultSetWrapper rsw, RowBounds rowBounds) { + this.resultSetHandler = resultSetHandler; + this.resultMap = resultMap; + this.rsw = rsw; + this.rowBounds = rowBounds; + } + + @Override + public boolean isOpen() { + return status == CursorStatus.OPEN; + } + + @Override + public boolean isConsumed() { + return status == CursorStatus.CONSUMED; + } + + @Override + public int getCurrentIndex() { + return rowBounds.getOffset() + cursorIterator.iteratorIndex; + } + + @Override + public Iterator iterator() { + if (iteratorRetrieved) { + throw new IllegalStateException("Cannot open more than one iterator on a Cursor"); } - - public DefaultCursor(DefaultResultSetHandler resultSetHandler, ResultMap resultMap, ResultSetWrapper rsw, RowBounds rowBounds) { - this.resultSetHandler = resultSetHandler; - this.resultMap = resultMap; - this.rsw = rsw; - this.rowBounds = rowBounds; + if (isClosed()) { + throw new IllegalStateException("A Cursor is already closed."); } - - @Override - public boolean isOpen() { - return status == CursorStatus.OPEN; + iteratorRetrieved = true; + return cursorIterator; + } + + @Override + public void close() { + if (isClosed()) { + return; } - @Override - public boolean isConsumed() { - return status == CursorStatus.CONSUMED; - } + ResultSet rs = rsw.getResultSet(); + try { + if (rs != null) { + Statement statement = rs.getStatement(); - @Override - public int getCurrentIndex() { - return rowBounds.getOffset() + cursorIterator.iteratorIndex; + rs.close(); + if (statement != null) { + statement.close(); + } + } + status = CursorStatus.CLOSED; + } catch (SQLException e) { + // ignore } + } - @Override - public Iterator iterator() { - if (iteratorRetrieved) { - throw new IllegalStateException("Cannot open more than one iterator on a Cursor"); - } - if (isClosed()) { - throw new IllegalStateException("A Cursor is already closed."); - } - iteratorRetrieved = true; - return cursorIterator; + protected T fetchNextUsingRowBound() { + T result = fetchNextObjectFromDatabase(); + while (result != null && indexWithRowBound < rowBounds.getOffset()) { + result = fetchNextObjectFromDatabase(); } + return result; + } - @Override - public void close() { - if (isClosed()) { - return; - } + protected T fetchNextObjectFromDatabase() { + if (isClosed()) { + return null; + } - ResultSet rs = rsw.getResultSet(); - try { - if (rs != null) { - Statement statement = rs.getStatement(); - - rs.close(); - if (statement != null) { - statement.close(); - } - } - status = CursorStatus.CLOSED; - } catch (SQLException e) { - // ignore - } + try { + status = CursorStatus.OPEN; + resultSetHandler.handleRowValues(rsw, resultMap, objectWrapperResultHandler, RowBounds.DEFAULT, null); + } catch (SQLException e) { + throw new RuntimeException(e); } - protected T fetchNextUsingRowBound() { - T result = fetchNextObjectFromDatabase(); - while (result != null && indexWithRowBound < rowBounds.getOffset()) { - result = fetchNextObjectFromDatabase(); - } - return result; + T next = objectWrapperResultHandler.result; + if (next != null) { + indexWithRowBound++; + } + // No more object or limit reached + if (next == null || getReadItemsCount() == rowBounds.getOffset() + rowBounds.getLimit()) { + close(); + status = CursorStatus.CONSUMED; } + objectWrapperResultHandler.result = null; - protected T fetchNextObjectFromDatabase() { - if (isClosed()) { - return null; - } + return next; + } - try { - status = CursorStatus.OPEN; - resultSetHandler.handleRowValues(rsw, resultMap, objectWrapperResultHandler, RowBounds.DEFAULT, null); - } catch (SQLException e) { - throw new RuntimeException(e); - } + private boolean isClosed() { + return status == CursorStatus.CLOSED || status == CursorStatus.CONSUMED; + } - T next = objectWrapperResultHandler.result; - if (next != null) { - indexWithRowBound++; - } - // No more object or limit reached - if (next == null || getReadItemsCount() == rowBounds.getOffset() + rowBounds.getLimit()) { - close(); - status = CursorStatus.CONSUMED; - } - objectWrapperResultHandler.result = null; + private int getReadItemsCount() { + return indexWithRowBound + 1; + } - return next; - } + private static class ObjectWrapperResultHandler implements ResultHandler { - private boolean isClosed() { - return status == CursorStatus.CLOSED || status == CursorStatus.CONSUMED; - } + private T result; - private int getReadItemsCount() { - return indexWithRowBound + 1; + @Override + public void handleResult(ResultContext context) { + this.result = context.getResultObject(); + context.stop(); } + } - private static class ObjectWrapperResultHandler implements ResultHandler { - - private T result; + private class CursorIterator implements Iterator { - @Override - public void handleResult(ResultContext context) { - this.result = context.getResultObject(); - context.stop(); - } - } + /** + * Holder for the next object to be returned + */ + T object; - private class CursorIterator implements Iterator { + /** + * Index of objects returned using next(), and as such, visible to users. + */ + int iteratorIndex = -1; - /** - * Holder for the next object to be returned - */ - T object; + @Override + public boolean hasNext() { + if (object == null) { + object = fetchNextUsingRowBound(); + } + return object != null; + } - /** - * Index of objects returned using next(), and as such, visible to users. - */ - int iteratorIndex = -1; + @Override + public T next() { + // Fill next with object fetched from hasNext() + T next = object; - @Override - public boolean hasNext() { - if (object == null) { - object = fetchNextUsingRowBound(); - } - return object != null; - } + if (next == null) { + next = fetchNextUsingRowBound(); + } - @Override - public T next() { - // Fill next with object fetched from hasNext() - T next = object; - - if (next == null) { - next = fetchNextUsingRowBound(); - } - - if (next != null) { - object = null; - iteratorIndex++; - return next; - } - throw new NoSuchElementException(); - } + if (next != null) { + object = null; + iteratorIndex++; + return next; + } + throw new NoSuchElementException(); + } - @Override - public void remove() { - throw new UnsupportedOperationException("Cannot remove element from Cursor"); - } + @Override + public void remove() { + throw new UnsupportedOperationException("Cannot remove element from Cursor"); } + } } diff --git a/src/test/java/org/apache/ibatis/submitted/cursor_nested/CursorNestedTest.java b/src/test/java/org/apache/ibatis/submitted/cursor_nested/CursorNestedTest.java index 02c3f814622..d8b6ea200ee 100644 --- a/src/test/java/org/apache/ibatis/submitted/cursor_nested/CursorNestedTest.java +++ b/src/test/java/org/apache/ibatis/submitted/cursor_nested/CursorNestedTest.java @@ -31,75 +31,75 @@ public class CursorNestedTest { - private static SqlSessionFactory sqlSessionFactory; - - @BeforeClass - public static void setUp() throws Exception { - // create a SqlSessionFactory - try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cursor_nested/mybatis-config.xml")) { - sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); - } - - // populate in-memory database - BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), - "org/apache/ibatis/submitted/cursor_nested/CreateDB.sql"); + private static SqlSessionFactory sqlSessionFactory; + + @BeforeClass + public static void setUp() throws Exception { + // create a SqlSessionFactory + try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cursor_nested/mybatis-config.xml")) { + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } - @Test - public void shouldGetAllUser() { - Cursor usersCursor; - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - usersCursor = mapper.getAllUsers(); - - Assert.assertFalse(usersCursor.isOpen()); - // Retrieving iterator, fetching is not started - Iterator iterator = usersCursor.iterator(); - - // Check if hasNext, fetching is started - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - - User user = iterator.next(); - Assert.assertEquals(2, user.getGroups().size()); - Assert.assertEquals(3, user.getRoles().size()); - - user = iterator.next(); - Assert.assertEquals(1, user.getGroups().size()); - Assert.assertEquals(3, user.getRoles().size()); - - user = iterator.next(); - Assert.assertEquals(3, user.getGroups().size()); - Assert.assertEquals(1, user.getRoles().size()); - - user = iterator.next(); - Assert.assertEquals(2, user.getGroups().size()); - Assert.assertEquals(2, user.getRoles().size()); - - // Check no more elements - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } - Assert.assertFalse(usersCursor.isOpen()); + // populate in-memory database + BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), + "org/apache/ibatis/submitted/cursor_nested/CreateDB.sql"); + } + + @Test + public void shouldGetAllUser() { + Cursor usersCursor; + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + usersCursor = mapper.getAllUsers(); + + Assert.assertFalse(usersCursor.isOpen()); + // Retrieving iterator, fetching is not started + Iterator iterator = usersCursor.iterator(); + + // Check if hasNext, fetching is started + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); + + User user = iterator.next(); + Assert.assertEquals(2, user.getGroups().size()); + Assert.assertEquals(3, user.getRoles().size()); + + user = iterator.next(); + Assert.assertEquals(1, user.getGroups().size()); + Assert.assertEquals(3, user.getRoles().size()); + + user = iterator.next(); + Assert.assertEquals(3, user.getGroups().size()); + Assert.assertEquals(1, user.getRoles().size()); + + user = iterator.next(); + Assert.assertEquals(2, user.getGroups().size()); + Assert.assertEquals(2, user.getRoles().size()); + + // Check no more elements + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); } + Assert.assertFalse(usersCursor.isOpen()); + } - @Test - public void testCursorWithRowBound() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(2, 1)); + @Test + public void testCursorWithRowBound() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(2, 1)); - Iterator iterator = usersCursor.iterator(); + Iterator iterator = usersCursor.iterator(); - Assert.assertTrue(iterator.hasNext()); - User user = iterator.next(); - Assert.assertEquals("User3", user.getName()); - Assert.assertEquals(2, usersCursor.getCurrentIndex()); + Assert.assertTrue(iterator.hasNext()); + User user = iterator.next(); + Assert.assertEquals("User3", user.getName()); + Assert.assertEquals(2, usersCursor.getCurrentIndex()); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); } + } } diff --git a/src/test/java/org/apache/ibatis/submitted/cursor_simple/CursorSimpleTest.java b/src/test/java/org/apache/ibatis/submitted/cursor_simple/CursorSimpleTest.java index 66d68e9d111..8bda75628cd 100644 --- a/src/test/java/org/apache/ibatis/submitted/cursor_simple/CursorSimpleTest.java +++ b/src/test/java/org/apache/ibatis/submitted/cursor_simple/CursorSimpleTest.java @@ -35,357 +35,356 @@ public class CursorSimpleTest { - private static SqlSessionFactory sqlSessionFactory; - - @BeforeClass - public static void setUp() throws Exception { - // create a SqlSessionFactory - try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cursor_simple/mybatis-config.xml")) { - sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); - } - - // populate in-memory database - BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), - "org/apache/ibatis/submitted/cursor_simple/CreateDB.sql"); - } + private static SqlSessionFactory sqlSessionFactory; - @Test - public void shouldGetAllUser() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - Cursor usersCursor = mapper.getAllUsers(); + @BeforeClass + public static void setUp() throws Exception { + // create a SqlSessionFactory + try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cursor_simple/mybatis-config.xml")) { + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + } - Assert.assertFalse(usersCursor.isOpen()); + // populate in-memory database + BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), + "org/apache/ibatis/submitted/cursor_simple/CreateDB.sql"); + } - // Cursor is just created, current index is -1 - Assert.assertEquals(-1, usersCursor.getCurrentIndex()); + @Test + public void shouldGetAllUser() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Cursor usersCursor = mapper.getAllUsers(); - Iterator iterator = usersCursor.iterator(); + Assert.assertFalse(usersCursor.isOpen()); - // Check if hasNext, fetching is started - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); + // Cursor is just created, current index is -1 + Assert.assertEquals(-1, usersCursor.getCurrentIndex()); - // next() has not been called, index is still -1 - Assert.assertEquals(-1, usersCursor.getCurrentIndex()); + Iterator iterator = usersCursor.iterator(); - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); - Assert.assertEquals(0, usersCursor.getCurrentIndex()); + // Check if hasNext, fetching is started + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); - user = iterator.next(); - Assert.assertEquals("User2", user.getName()); - Assert.assertEquals(1, usersCursor.getCurrentIndex()); + // next() has not been called, index is still -1 + Assert.assertEquals(-1, usersCursor.getCurrentIndex()); - user = iterator.next(); - Assert.assertEquals("User3", user.getName()); - Assert.assertEquals(2, usersCursor.getCurrentIndex()); + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); + Assert.assertEquals(0, usersCursor.getCurrentIndex()); - user = iterator.next(); - Assert.assertEquals("User4", user.getName()); - Assert.assertEquals(3, usersCursor.getCurrentIndex()); + user = iterator.next(); + Assert.assertEquals("User2", user.getName()); + Assert.assertEquals(1, usersCursor.getCurrentIndex()); - user = iterator.next(); - Assert.assertEquals("User5", user.getName()); - Assert.assertEquals(4, usersCursor.getCurrentIndex()); + user = iterator.next(); + Assert.assertEquals("User3", user.getName()); + Assert.assertEquals(2, usersCursor.getCurrentIndex()); - // Check no more elements - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } - } + user = iterator.next(); + Assert.assertEquals("User4", user.getName()); + Assert.assertEquals(3, usersCursor.getCurrentIndex()); - @Test - public void testCursorClosedOnSessionClose() { - Cursor usersCursor; - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - usersCursor = mapper.getAllUsers(); + user = iterator.next(); + Assert.assertEquals("User5", user.getName()); + Assert.assertEquals(4, usersCursor.getCurrentIndex()); - Assert.assertFalse(usersCursor.isOpen()); + // Check no more elements + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); + } + } - Iterator iterator = usersCursor.iterator(); + @Test + public void testCursorClosedOnSessionClose() { + Cursor usersCursor; + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + usersCursor = mapper.getAllUsers(); - // Check if hasNext, fetching is started - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); + Assert.assertFalse(usersCursor.isOpen()); - // Consume only the first result - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); + Iterator iterator = usersCursor.iterator(); - // Check there is still remaining elements - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - } + // Check if hasNext, fetching is started + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); - // The cursor was not fully consumed, but it should be close since we closed the session - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - } + // Consume only the first result + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); - @Test - public void testCursorWithRowBound() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - // RowBound starting at offset 1 and limiting to 2 items - Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 3)); - - Iterator iterator = usersCursor.iterator(); - - User user = iterator.next(); - Assert.assertEquals("User2", user.getName()); - Assert.assertEquals(1, usersCursor.getCurrentIndex()); - - // Calling hasNext() before next() - Assert.assertTrue(iterator.hasNext()); - user = iterator.next(); - Assert.assertEquals("User3", user.getName()); - Assert.assertEquals(2, usersCursor.getCurrentIndex()); - - // Calling next() without a previous hasNext() call - user = iterator.next(); - Assert.assertEquals("User4", user.getName()); - Assert.assertEquals(3, usersCursor.getCurrentIndex()); - - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } + // Check there is still remaining elements + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); } - @Test - public void testCursorIteratorNoSuchElementExceptionWithHasNext() throws IOException { - - try (SqlSession sqlSession = sqlSessionFactory.openSession(); - Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) { - try { - Iterator iterator = usersCursor.iterator(); - - User user = iterator.next(); - Assert.assertEquals("User2", user.getName()); - Assert.assertEquals(1, usersCursor.getCurrentIndex()); - - Assert.assertFalse(iterator.hasNext()); - iterator.next(); - Assert.fail("We should have failed since we call next() when hasNext() returned false"); - } catch (NoSuchElementException e) { - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } - } + // The cursor was not fully consumed, but it should be close since we closed the session + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); + } + + @Test + public void testCursorWithRowBound() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + // RowBound starting at offset 1 and limiting to 2 items + Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 3)); + + Iterator iterator = usersCursor.iterator(); + + User user = iterator.next(); + Assert.assertEquals("User2", user.getName()); + Assert.assertEquals(1, usersCursor.getCurrentIndex()); + + // Calling hasNext() before next() + Assert.assertTrue(iterator.hasNext()); + user = iterator.next(); + Assert.assertEquals("User3", user.getName()); + Assert.assertEquals(2, usersCursor.getCurrentIndex()); + + // Calling next() without a previous hasNext() call + user = iterator.next(); + Assert.assertEquals("User4", user.getName()); + Assert.assertEquals(3, usersCursor.getCurrentIndex()); + + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); } + } - @Test - public void testCursorIteratorNoSuchElementExceptionNoHasNext() throws IOException { - try (SqlSession sqlSession = sqlSessionFactory.openSession(); - Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) { - try { - Iterator iterator = usersCursor.iterator(); - User user = iterator.next(); - Assert.assertEquals("User2", user.getName()); - Assert.assertEquals(1, usersCursor.getCurrentIndex()); - - // Trying next() without hasNext() - iterator.next(); - Assert.fail("We should have failed since we call next() when is no more items"); - } catch (NoSuchElementException e) { - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } - } - } + @Test + public void testCursorIteratorNoSuchElementExceptionWithHasNext() throws IOException { + try (SqlSession sqlSession = sqlSessionFactory.openSession(); + Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) { + try { + Iterator iterator = usersCursor.iterator(); - @Test - public void testCursorWithBadRowBound() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - // Trying to start at offset 10 (which does not exist, since there is only 4 items) - Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(10, 2)); - Iterator iterator = usersCursor.iterator(); + User user = iterator.next(); + Assert.assertEquals("User2", user.getName()); + Assert.assertEquals(1, usersCursor.getCurrentIndex()); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - } + Assert.assertFalse(iterator.hasNext()); + iterator.next(); + Assert.fail("We should have failed since we call next() when hasNext() returned false"); + } catch (NoSuchElementException e) { + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); + } + } + } + + @Test + public void testCursorIteratorNoSuchElementExceptionNoHasNext() throws IOException { + try (SqlSession sqlSession = sqlSessionFactory.openSession(); + Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(1, 1))) { + try { + Iterator iterator = usersCursor.iterator(); + User user = iterator.next(); + Assert.assertEquals("User2", user.getName()); + Assert.assertEquals(1, usersCursor.getCurrentIndex()); + + // Trying next() without hasNext() + iterator.next(); + Assert.fail("We should have failed since we call next() when is no more items"); + } catch (NoSuchElementException e) { + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); + } + } + } + + @Test + public void testCursorWithBadRowBound() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + // Trying to start at offset 10 (which does not exist, since there is only 4 items) + Cursor usersCursor = sqlSession.selectCursor("getAllUsers", null, new RowBounds(10, 2)); + Iterator iterator = usersCursor.iterator(); + + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); } + } - @Test - public void testCursorMultipleHasNextCall() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - Cursor usersCursor = mapper.getAllUsers(); + @Test + public void testCursorMultipleHasNextCall() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Cursor usersCursor = mapper.getAllUsers(); - Iterator iterator = usersCursor.iterator(); + Iterator iterator = usersCursor.iterator(); - Assert.assertEquals(-1, usersCursor.getCurrentIndex()); + Assert.assertEquals(-1, usersCursor.getCurrentIndex()); - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); - Assert.assertEquals(0, usersCursor.getCurrentIndex()); + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); + Assert.assertEquals(0, usersCursor.getCurrentIndex()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - // assert that index has not changed after hasNext() call - Assert.assertEquals(0, usersCursor.getCurrentIndex()); - } + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + // assert that index has not changed after hasNext() call + Assert.assertEquals(0, usersCursor.getCurrentIndex()); } - - @Test - public void testCursorMultipleIteratorCall() { - Iterator iterator2 = null; - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - Cursor usersCursor = mapper.getAllUsers(); - - Iterator iterator = usersCursor.iterator(); - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); - Assert.assertEquals(0, usersCursor.getCurrentIndex()); - - iterator2 = usersCursor.iterator(); - iterator2.hasNext(); - Assert.fail("We should have failed since calling iterator several times is not allowed"); - } catch (IllegalStateException e) { - Assert.assertNull("iterator2 should be null", iterator2); - return; - } - Assert.fail("Should have returned earlier"); + } + + @Test + public void testCursorMultipleIteratorCall() { + Iterator iterator2 = null; + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Cursor usersCursor = mapper.getAllUsers(); + + Iterator iterator = usersCursor.iterator(); + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); + Assert.assertEquals(0, usersCursor.getCurrentIndex()); + + iterator2 = usersCursor.iterator(); + iterator2.hasNext(); + Assert.fail("We should have failed since calling iterator several times is not allowed"); + } catch (IllegalStateException e) { + Assert.assertNull("iterator2 should be null", iterator2); + return; } + Assert.fail("Should have returned earlier"); + } - @Test - public void testCursorMultipleCloseCall() throws IOException { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); - Cursor usersCursor = mapper.getAllUsers(); + @Test + public void testCursorMultipleCloseCall() throws IOException { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); + Cursor usersCursor = mapper.getAllUsers(); - Assert.assertFalse(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isOpen()); - Iterator iterator = usersCursor.iterator(); + Iterator iterator = usersCursor.iterator(); - // Check if hasNext, fetching is started - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); + // Check if hasNext, fetching is started + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); - // Consume only the first result - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); + // Consume only the first result + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); - usersCursor.close(); - // Check multiple close are no-op - usersCursor.close(); + usersCursor.close(); + // Check multiple close are no-op + usersCursor.close(); - // hasNext now return false, since the cursor is closed - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - } + // hasNext now return false, since the cursor is closed + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); } + } - @Test - public void testCursorUsageAfterClose() throws IOException { + @Test + public void testCursorUsageAfterClose() throws IOException { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - Mapper mapper = sqlSession.getMapper(Mapper.class); + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + Mapper mapper = sqlSession.getMapper(Mapper.class); - Cursor usersCursor = mapper.getAllUsers(); - try { - Iterator iterator = usersCursor.iterator(); - User user = iterator.next(); - Assert.assertEquals("User1", user.getName()); - Assert.assertEquals(0, usersCursor.getCurrentIndex()); + Cursor usersCursor = mapper.getAllUsers(); + try { + Iterator iterator = usersCursor.iterator(); + User user = iterator.next(); + Assert.assertEquals("User1", user.getName()); + Assert.assertEquals(0, usersCursor.getCurrentIndex()); - user = iterator.next(); - Assert.assertEquals("User2", user.getName()); - Assert.assertEquals(1, usersCursor.getCurrentIndex()); + user = iterator.next(); + Assert.assertEquals("User2", user.getName()); + Assert.assertEquals(1, usersCursor.getCurrentIndex()); - usersCursor.close(); + usersCursor.close(); - // hasNext now return false, since the cursor is closed - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - - // trying next() will fail - iterator.next(); + // hasNext now return false, since the cursor is closed + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); - Assert.fail("We should have failed with NoSuchElementException since Cursor is closed"); - } catch (NoSuchElementException e) { - // We had an exception and current index has not changed - Assert.assertEquals(1, usersCursor.getCurrentIndex()); - usersCursor.close(); - return; - } - } + // trying next() will fail + iterator.next(); - Assert.fail("Should have returned earlier"); + Assert.fail("We should have failed with NoSuchElementException since Cursor is closed"); + } catch (NoSuchElementException e) { + // We had an exception and current index has not changed + Assert.assertEquals(1, usersCursor.getCurrentIndex()); + usersCursor.close(); + return; + } } - @Test - public void shouldGetAllUserUsingAnnotationBasedMapper() { - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - sqlSession.getConfiguration().getMapperRegistry().addMapper(AnnotationMapper.class); - AnnotationMapper mapper = sqlSession.getMapper(AnnotationMapper.class); - Cursor usersCursor = mapper.getAllUsers(); - - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertFalse(usersCursor.isConsumed()); - Assert.assertEquals(-1, usersCursor.getCurrentIndex()); - - List userList = new ArrayList(); - for (User user : usersCursor){ - userList.add(user); - Assert.assertEquals(userList.size() -1, usersCursor.getCurrentIndex()); - } - - Assert.assertFalse(usersCursor.isOpen()); - Assert.assertTrue(usersCursor.isConsumed()); - Assert.assertEquals(4, usersCursor.getCurrentIndex()); - - Assert.assertEquals(5, userList.size()); - User user = userList.get(0); - Assert.assertEquals("User1", user.getName()); - user = userList.get(1); - Assert.assertEquals("User2", user.getName()); - user = userList.get(2); - Assert.assertEquals("User3", user.getName()); - user = userList.get(3); - Assert.assertEquals("User4", user.getName()); - user = userList.get(4); - Assert.assertEquals("User5", user.getName()); - } + Assert.fail("Should have returned earlier"); + } + + @Test + public void shouldGetAllUserUsingAnnotationBasedMapper() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + sqlSession.getConfiguration().getMapperRegistry().addMapper(AnnotationMapper.class); + AnnotationMapper mapper = sqlSession.getMapper(AnnotationMapper.class); + Cursor usersCursor = mapper.getAllUsers(); + + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertFalse(usersCursor.isConsumed()); + Assert.assertEquals(-1, usersCursor.getCurrentIndex()); + + List userList = new ArrayList(); + for (User user : usersCursor) { + userList.add(user); + Assert.assertEquals(userList.size() - 1, usersCursor.getCurrentIndex()); + } + + Assert.assertFalse(usersCursor.isOpen()); + Assert.assertTrue(usersCursor.isConsumed()); + Assert.assertEquals(4, usersCursor.getCurrentIndex()); + + Assert.assertEquals(5, userList.size()); + User user = userList.get(0); + Assert.assertEquals("User1", user.getName()); + user = userList.get(1); + Assert.assertEquals("User2", user.getName()); + user = userList.get(2); + Assert.assertEquals("User3", user.getName()); + user = userList.get(3); + Assert.assertEquals("User4", user.getName()); + user = userList.get(4); + Assert.assertEquals("User5", user.getName()); } + } - @Test - public void shouldThrowIllegalStateExceptionUsingIteratorOnSessionClosed() { - Cursor usersCursor; - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers(); - } - try { - usersCursor.iterator(); - Assert.fail("Should throws the IllegalStateException when call the iterator method after session is closed."); - } catch (IllegalStateException e) { - Assert.assertEquals("A Cursor is already closed.", e.getMessage()); - } - - // verify for checking order - try (SqlSession sqlSession = sqlSessionFactory.openSession()) { - usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers(); - usersCursor.iterator(); - } - try { - usersCursor.iterator(); - Assert.fail("Should throws the IllegalStateException when call the iterator already."); - } catch (IllegalStateException e) { - Assert.assertEquals("Cannot open more than one iterator on a Cursor", e.getMessage()); - } + @Test + public void shouldThrowIllegalStateExceptionUsingIteratorOnSessionClosed() { + Cursor usersCursor; + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers(); + } + try { + usersCursor.iterator(); + Assert.fail("Should throws the IllegalStateException when call the iterator method after session is closed."); + } catch (IllegalStateException e) { + Assert.assertEquals("A Cursor is already closed.", e.getMessage()); + } + // verify for checking order + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + usersCursor = sqlSession.getMapper(Mapper.class).getAllUsers(); + usersCursor.iterator(); } + try { + usersCursor.iterator(); + Assert.fail("Should throws the IllegalStateException when call the iterator already."); + } catch (IllegalStateException e) { + Assert.assertEquals("Cannot open more than one iterator on a Cursor", e.getMessage()); + } + + } }