1. 概要

この記事では、JDBCResultSetの行数をカウントするさまざまな方法を見ていきます。

2. ResultSet行のカウント

ResultSet の行をカウントすることは、この情報を提供するAPIメソッドがないため簡単ではありません。 これは、JDBCクエリがすべての結果をすぐにフェッチするわけではないためです。 行の結果は、ResultSet.nextメソッドを使用して要求するたびにデータベースからロードされます。

JDBCクエリを実行するとき、事前にいくつの結果が得られるかを知ることはできません。 代わりに、それらすべてを調べる必要があり、最後に到達したときにのみ、使用可能な行の数を確認できます。

これを行うには、標準またはスクロール可能なResultSetを使用する2つの方法があります。

3. 標準ResultSet

クエリ結果をカウントする最も簡単な方法は、すべてを繰り返し処理し、結果ごとにカウンター変数をインクリメントすることです。

データベース接続用の単一のパラメーターを使用してStandardRowCounterクラスを作成しましょう。

class StandardRowCounter {
    Connection conn;

    StandardRowCounter(Connection conn) {
        this.conn = conn;
    }
}

このクラスには、SQLクエリを String として受け取り、 ResultSet を反復処理して行数を返し、結果ごとにカウンター変数をインクリメントする単一のメソッドが含まれます。

カウンターメソッドにgetQueryRowCountという名前を付けましょう。

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;
    }
}

try-with-resources ブロックを使用して、JDBCリソースを自動的に閉じることに注意してください。

実装をテストするために、インメモリデータベースを利用して、3つのエントリを持つテーブルをすばやく生成します。

それを手にして、単純なmainメソッドを使用してRowCounterAppを作成しましょう。

class RowCounterApp {

    public static void main(String[] args) throws SQLException {
        Connection conn = createDummyDB();

        String selectQuery = "SELECT * FROM STORAGE";

        StandardRowCounter standardCounter = new StandardRowCounter(conn);
        assert standardCounter.getQueryRowCount(selectQuery) == 3;
    }

    static Connection createDummyDB() throws SQLException {
        ...
    }

}

上記の方法は、どのデータベースでも機能します。 ただし、データベースドライバーがそれをサポートしている場合は、同じ結果を達成するために使用できるより高度なAPIがいくつかあります。

4. スクロール可能ResultSet

オーバーロードされたStatementメソッドcreateStatement、を使用することにより、クエリの実行後にスクロール可能なResultSetを作成するように要求できます。 スクロール可能なバージョンでは、previousなどのより高度なトラバーサル方法を使用して後方に移動できます。 この例では、 last メソッドを使用して、 Result Set の最後に移動し、指定された最後のエントリの行番号を取得します。 getRowメソッドによる。

ScrollableRowCounterクラスを作成しましょう。

class ScrollableRowCounter {
    Connection conn;

    ScrollableRowCounter(Connection conn) {
        this.conn = conn;
    }
}

StandardRowCounter と同様に、使用するフィールドはデータベースConnectionのみです。

ここでも、getQueryRowCountメソッドを使用します。

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();
        return scrollableRS.getRow();
    }
}

スクロール可能なResultSet、を取得するには、ResultSet.TYPE_SCROLL_INSENSITIVE定数をcreateStatementメソッドに指定する必要があります。 さらに、同時実行モードの値を指定する必要がありますが、この場合とは無関係であるため、デフォルトのResultSet。CONCUR_READ_ONLY定数を使用します。 JDBCドライバーがこの操作モードをサポートしていない場合、例外がスローされます。

RowCountAppを使用して新しい実装をテストしてみましょう。

ScrollableRowCounter scrollableCounter = new ScrollableRowCounter(conn);
assert scrollableCounter.getQueryRowCount(selectQuery) == 3;

5. パフォーマンスに関する考慮事項

上記の実装は単純ですが、 ResultSet の必須のトラバーサルのため、は最高のパフォーマンスを発揮しません。 このため、通常、行カウント操作にはCOUNTタイプのクエリを使用することをお勧めします。

簡単な例は次のとおりです。

SELECT COUNT(*) FROM STORAGE

これにより、STORAGEテーブルの行数を含む単一の列を持つ単一の行が返されます。

6. 結論

この記事では、ResultSetの行数を取得するさまざまな方法について説明しました。

いつものように、この記事のソースコードはGitHubから入手できます。