diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/RowCounterApp.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/RowCounterApp.java new file mode 100644 index 0000000000..3126241d74 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/RowCounterApp.java @@ -0,0 +1,43 @@ +package com.baeldung.resultsetrowcount; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +class RowCounterApp { + + static Logger logger = LoggerFactory.getLogger(RowCounterApp.class); + + public static void main(String[] args) throws SQLException { + Connection conn = createDummyDB(); + + String selectQuery = "SELECT * FROM STORAGE"; + + StandardRowCounter standardCounter = new StandardRowCounter(conn); + logger.info("Standard counter count: {}", standardCounter.getQueryRowCount(selectQuery)); + + ScrollableRowCounter scrollableCounter = new ScrollableRowCounter(conn); + logger.info("Scrollable counter count: {}", scrollableCounter.getQueryRowCount(selectQuery)); + } + + static Connection createDummyDB() throws SQLException { + String dbUrl = "jdbc:h2:mem:testdb"; + Connection conn = DriverManager.getConnection(dbUrl); + try (Statement statement = conn.createStatement()) { + String sql = "CREATE TABLE STORAGE (id INTEGER not null, val VARCHAR(50), PRIMARY KEY (id))"; + statement.executeUpdate(sql); + sql = "INSERT INTO STORAGE VALUES (1, 'Entry A')"; + statement.executeUpdate(sql); + sql = "INSERT INTO STORAGE VALUES (2, 'Entry A')"; + statement.executeUpdate(sql); + sql = "INSERT INTO STORAGE VALUES (3, 'Entry A')"; + statement.executeUpdate(sql); + } + return conn; + } + +} diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/ScrollableRowCounter.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/ScrollableRowCounter.java new file mode 100644 index 0000000000..ecf74a78a8 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/ScrollableRowCounter.java @@ -0,0 +1,30 @@ +package com.baeldung.resultsetrowcount; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A ResultSet counter that uses a scrollable cursor. + * Scrollable cursors must be supported by the underlying JDBC driver + * and will not always be available for use. + */ +class ScrollableRowCounter { + + Connection conn; + + ScrollableRowCounter(Connection conn) { + this.conn = conn; + } + + int getQueryRowCount(String query) throws SQLException { + try (Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet scrollableRS = statement.executeQuery(query)) { + scrollableRS.last(); // check if we need a scrollable type for this (probably) + return scrollableRS.getRow(); + // if we want to process the result set data we can move the cursor back to + // the beginning using the scrollableRS.beforeFirst() method + } + } + +} diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/StandardRowCounter.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/StandardRowCounter.java new file mode 100644 index 0000000000..de51834487 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/resultsetrowcount/StandardRowCounter.java @@ -0,0 +1,32 @@ +package com.baeldung.resultsetrowcount; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A ResultSet counter that iterates through the query + * results and increments a counter variable until it + * reaches the last result. + * + * This solution will work on all cases but is ineffective, + * especially if the ResultSet will be discarded afterwards. + */ +class StandardRowCounter { + Connection conn; + + StandardRowCounter(Connection conn) { + this.conn = conn; + } + + int getQueryRowCount(String query) throws SQLException { + try (Statement statement = conn.createStatement(); ResultSet standardRS = statement.executeQuery(query)) { + int size = 0; + while (standardRS.next()) { + size++; + } + return size; + } + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/ScrollableRowCounterUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/ScrollableRowCounterUnitTest.java new file mode 100644 index 0000000000..959fa817b4 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/ScrollableRowCounterUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.resultsetrowcount; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.SQLException; + +class ScrollableRowCounterUnitTest { + + Connection conn; + + @BeforeEach + void setUp() throws SQLException { + conn = RowCounterApp.createDummyDB(); + } + + @AfterEach + void tearDown() throws SQLException { + conn.close(); + } + + @Test + public void givenDummyDBWithThreeRows_whenAskingForScrollableRowCountForSelectStar_thenCountIsThree() throws SQLException { + ScrollableRowCounter counter = new ScrollableRowCounter(conn); + + int queryRowCount = counter.getQueryRowCount("SELECT * FROM STORAGE"); + + Assertions.assertEquals(3, queryRowCount); + } + + @Test + public void givenDummyDBWithThreeRows_whenAskingForScrollableRowCountForSelect1and2_thenCountIsTwo() throws SQLException { + ScrollableRowCounter counter = new ScrollableRowCounter(conn); + + int queryRowCount = counter.getQueryRowCount("SELECT * FROM STORAGE WHERE ID IN (1,2)"); + + Assertions.assertEquals(2, queryRowCount); + } + +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/StandardRowCounterUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/StandardRowCounterUnitTest.java new file mode 100644 index 0000000000..e329b5800c --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/resultsetrowcount/StandardRowCounterUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.resultsetrowcount; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.SQLException; + +class StandardRowCounterUnitTest { + + Connection conn; + + @BeforeEach + void setUp() throws SQLException { + conn = RowCounterApp.createDummyDB(); + } + + @AfterEach + void tearDown() throws SQLException { + conn.close(); + } + + @Test + public void givenDummyDBWithThreeRows_whenAskingForStandardRowCountForSelectStar_thenCountIsThree() throws SQLException { + StandardRowCounter counter = new StandardRowCounter(conn); + + int queryRowCount = counter.getQueryRowCount("SELECT * FROM STORAGE"); + + Assertions.assertEquals(3, queryRowCount); + } + + @Test + public void givenDummyDBWithThreeRows_whenAskingForStandardRowCountForSelect1and2_thenCountIsTwo() throws SQLException { + StandardRowCounter counter = new StandardRowCounter(conn); + + int queryRowCount = counter.getQueryRowCount("SELECT * FROM STORAGE WHERE ID IN (1,2)"); + + Assertions.assertEquals(2, queryRowCount); + } + +}