JavaのResultSetで、クエリ結果を順次処理

JavaのResultSetとは

ResultSetは、Javaのデータベース接続ライブラリであるJDBC(Java Database Connectivity)の一部です。
ResultSetは、SQLクエリを実行した結果として得られるデータを表すオブジェクトです。
具体的には、SELECTクエリを実行したときに返される表形式のデータを保持し、プログラムがそのデータにアクセスできるようにします。

主な機能と特徴は以下の通りです:

1. データの反復処理:
ResultSetは行ごとにデータを処理できるように設計されています。
次の行に進むためにnext()メソッドを使用します。

while (resultSet.next()) {
   // データの処理
}

2. データの取得:
ResultSetからデータを取得するために様々なメソッドが提供されています。
例えば、getString(), getInt(), getDouble()などを使用して、列データを取得します。

String name = resultSet.getString("name");
int age = resultSet.getInt("age");

3. カーソルの動き:
ResultSetには、前後に移動できるスクロール可能なカーソルがあります。
これは、TYPE_SCROLL_INSENSITIVEまたはTYPE_SCROLL_SENSITIVEのようなスクロールタイプのResultSetを作成することで実現できます。

4. 更新可能なResultSet:
ResultSetを使用してデータベースの内容を直接更新することもできます。
これは、CONCUR_UPDATABLEのような更新可能なResultSetを作成することで可能です。

resultSet.updateString("name", "newName");
resultSet.updateRow();

5. クローズの重要性:
ResultSetはデータベースリソースを消費するため、使用後はclose()メソッドで閉じる必要があります。

resultSet.close();

典型的なResultSetの使用例は以下のようになります:

// DBに接続してクエリを実行
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM table_name");

// 一行ずつ処理
while (resultSet.next()) {
    String column1 = resultSet.getString("column1");
    int column2 = resultSet.getInt("column2");
    // データ処理
}

// リソースをクローズ
resultSet.close();
statement.close();
connection.close();

ResultSetは、データベース操作を行う上で非常に重要な役割を果たし、データの取得と操作を効率的に行うための強力なツールです。

Mybatisを使う場合のResultSetの実装例

MyBatisは、SQLベースのORMフレームワークであり、JDBCを直接使用する代わりに、SQLマッピングを簡単に管理するための抽象化を提供します。
MyBatisを使用すると、SQLクエリの結果をJavaオブジェクトにマッピングする作業が大幅に簡素化されます。

以下は、MyBatisを使用してResultSetを処理する基本的な実装例です。

1. マッパーXMLファイル(UserMapper.xml):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectAllUsers" resultType="com.example.model.User">
        SELECT id, name, email FROM users
    </select>
</mapper>

2. マッパーインターフェース(UserMapper.java):

package com.example.mapper;

import com.example.model.User;
import java.util.List;

public interface UserMapper {
    List<User> selectAllUsers();
}

3. データモデルクラス(User.java):

package com.example.model;

@Data
public class User {
    private int id;
    private String name;
    private String email;
}

4. MyBatisを使用するサービスクラス(UserService.java):

package com.example.service;

import com.example.mapper.UserMapper;
import com.example.model.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;

public class UserService {
    private SqlSessionFactory sqlSessionFactory;

    public UserService() {
        String resource = "mybatis-config.xml";
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public List<User> getAllUsers() {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            return mapper.selectAllUsers();
        }
    }
}

5. アプリケーションのエントリーポイント(Main.java):

package com.example;

import com.example.model.User;
import com.example.service.UserService;

import java.util.List;

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserService();
        // 適切なJavaオブジェクトに変換
        List<User> users = userService.getAllUsers();

        // 手動でResultSetを操作する必要がない
        for (User user : users) {
            System.out.println("ID: " + user.getId() + ", Name: " + user.getName() + ", Email: " + user.getEmail());
        }
    }
}

この例では、MyBatisを使用してSQLクエリを実行し、その結果をUserオブジェクトのリストにマッピングしています。
MyBatisがJDBCのResultSetを内部的に処理し、結果を適切なJavaオブジェクトに変換してくれます。
これにより、手動でResultSetを操作する必要がなくなり、コードが簡潔になります。