java.sqlとjavax.sqlの特徴と違い

java.sqlとjavax.sqlの特徴と違い

java.sqlとjavax.sqlは、JavaでデータベースにアクセスするためのAPIを提供するパッケージです。
それぞれの特徴と違いについて説明します。

java.sql

java.sqlパッケージは、JDBC (Java Database Connectivity) APIのコア部分を提供します。
このパッケージは、Javaプログラムがデータベースにアクセスし、データを操作するための基本的なインターフェースとクラスを提供します。

主なクラスとインターフェース:

  • DriverManager: データベース接続を管理するためのクラス。
  • Connection: データベース接続を表すインターフェース。
  • Statement: SQL文を実行するためのインターフェース。
  • ResultSet: SQLクエリの結果セットを表すインターフェース。
  • SQLException: SQL操作中に発生する例外を表すクラス。

javax.sql

javax.sqlパッケージは、JDBC APIを補完し、より高度な機能を提供します。
特に、データソース (DataSource) を使用した接続管理やトランザクション管理を支援するためのAPIが含まれています。

主なクラスとインターフェース:

  • DataSource: データベース接続を取得するための標準的な方法を提供するインターフェース。
  • ConnectionPoolDataSource: 接続プール用のデータソースを提供するインターフェース。
  • PooledConnection: 接続プール内の個々の接続を表すインターフェース。
  • XADataSource: 分散トランザクションをサポートするデータソースを提供するインターフェース。
  • RowSet: データベースの行セットを操作するためのオブジェクト。

主な違い

  • 機能の範囲:

java.sqlは基本的なデータベース操作を提供しますが、javax.sqlはこれを補完し、接続プーリングや分散トランザクションといった高度な機能を提供します。

  • データソースのサポート:

javax.sqlは、DataSourceインターフェースを通じて、より柔軟で効率的な接続管理をサポートします。
これは特にエンタープライズアプリケーションで重要です。

  • トランザクション管理:

javax.sqlには、分散トランザクションをサポートするXADataSourceが含まれています。
これは複数のデータベースにまたがるトランザクションを管理するのに役立ちます。

これらの違いにより、java.sqlは基本的なデータベース操作を迅速に行いたい場合に適しており、javax.sqlはより複雑な接続管理やトランザクション管理が必要なエンタープライズレベルのアプリケーションに適しています。

java.sqlを用いた基本的なデータベース操作

java.sqlを用いた基本的なデータベース操作には、データベース接続の確立、データの挿入、クエリの実行、データの更新、データの削除などがあります。
以下に、これらの基本操作を行うための一般的な手順とコード例を示します。
DBはMySQLを使用しています。
※基本的にDB操作はフレームワークを通して行うことが主流のため、現場でこのような処理を書くことはないと思いますが、java.sqlの機能を示すためのコードです。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseConnection {
    public static void main(String[] args) {
        // DBの接続情報
        String url = "jdbc:mysql://localhost:3306/test_database";
        String user = "test_username";
        String password = "test_password";

        // データベースへの接続を確立
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            if (conn != null) {
                System.out.println("Connected to the database");
            }

            // データの挿入
            String insertSql = "INSERT INTO your_table (column1, column2) VALUES (?, ?)";
            PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
                pstmt.setString(1, "value1");
                pstmt.setString(2, "value2");

                int rowsInserted = pstmt.executeUpdate();
                if (rowsInserted > 0) {
                    System.out.println("A new record was inserted successfully!");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        // データベースへの接続を確立
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            if (conn != null) {
                System.out.println("Connected to the database");
            }

            // データの取得
            String selectSql = "SELECT column1, column2 FROM your_table";
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(selectSql)) {
                while (rs.next()) {
                    String column1 = rs.getString("column1");
                    String column2 = rs.getString("column2");
                    System.out.println(column1 + ", " + column2);
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        // データベースへの接続を確立
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            if (conn != null) {
                System.out.println("Connected to the database");
            }

            // データの更新
            String updateSql = "UPDATE your_table SET column1 = ? WHERE column2 = ?";
            PreparedStatement pstmt = conn.prepareStatement(updateSql)) {
                pstmt.setString(1, "new_value1");
                pstmt.setString(2, "value2");

                int rowsUpdated = pstmt.executeUpdate();
                if (rowsUpdated > 0) {
                    System.out.println("An existing record was updated successfully!");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        // データベースへの接続を確立
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            if (conn != null) {
                System.out.println("Connected to the database");
            }

            // データの削除
            String deleteSql = "DELETE FROM your_table WHERE column1 = ?";
            PreparedStatement pstmt = conn.prepareStatement(deleteSql)) {
                pstmt.setString(1, "value1");

                int rowsDeleted = pstmt.executeUpdate();
                if (rowsDeleted > 0) {
                    System.out.println("A record was deleted successfully!");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

java.sqlを用いた基本的なデータベース操作は上記のようになります。
繰り返しになりますが、現場ではフレームワークを用いてデータベースアクセスを行うため、上記のような書き方はしないと思われます。

javax.sqlを用いた高度なデータベース接続管理機能

javax.sqlパッケージは、Javaにおける高度なデータベース接続管理機能を提供します。
特に、エンタープライズレベルのアプリケーションでよく使われる接続プーリングや分散トランザクションなどの機能が含まれています。
以下に、これらの高度な機能の使用例を示します。

データソースを使用した接続(コネクション)プーリング

接続プーリングは、接続の作成と破棄のコストを削減し、アプリケーションのパフォーマンスを向上させます。
以下は、Apache Commons DBCPライブラリを使用して接続プーリングを設定し、データベースに接続する例です。
こちらもDBはMySQLを使用しています。

Mavenの依存関係

まず、pom.xmlに以下の依存関係を追加します。

<dependency>
    <groupId>commons-dbcp2</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>バージョン</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>バージョン</version>
</dependency>
コード例
import org.apache.commons.dbcp2.BasicDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class ConnectionPoolingExample {
    // コネクションプーリングの設定処理
    private static DataSource getDataSource() {
        BasicDataSource ds = new BasicDataSource();
        // DBの接続情報
        ds.setUrl("jdbc:mysql://localhost:3306/test_database");
        ds.setUsername("test_username");
        ds.setPassword("test_password");
        ds.setMinIdle(5);
        ds.setMaxIdle(10);
        ds.setMaxOpenPreparedStatements(100);

        return ds;
    }

    public static void main(String[] args) {
        DataSource dataSource = getDataSource();

        try (Connection conn = dataSource.getConnection();
             PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM your_table");
             ResultSet rs = pstmt.executeQuery()) {

            while (rs.next()) {
                String column1 = rs.getString("column1");
                String column2 = rs.getString("column2");
                System.out.println(column1 + ", " + column2);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

分散トランザクションのサポート

分散トランザクションは、複数のデータソースにまたがるトランザクションを管理するために使用されます。
以下は、javax.transactionパッケージとBitronix Transaction Managerを使用して分散トランザクションを管理する例です。

Mavenの依存関係

pom.xmlに以下の依存関係を追加します。

<dependency>
    <groupId>commons-dbcp2</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>バージョン</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>バージョン</version>
</dependency>
<dependency>
    <groupId>org.codehaus.btm</groupId>
    <artifactId>btm</artifactId>
    <version>バージョン</version>
</dependency>
コード例
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;

import javax.sql.DataSource;
import javax.transaction.Transactional;
import javax.transaction.UserTransaction;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DistributedTransactionExample {
    // コネクションプーリングの設定処理
    private static DataSource getDataSource(String name, String url, String username, String password) {
        PoolingDataSource ds = new PoolingDataSource();
        ds.setClassName("com.mysql.cj.jdbc.MysqlXADataSource");
        ds.setUniqueName(name);
        ds.setMaxPoolSize(5);
        ds.setAllowLocalTransactions(true);
        ds.getDriverProperties().put("user", username);
        ds.getDriverProperties().put("password", password);
        ds.getDriverProperties().put("URL", url);
        ds.init();

        return ds;
    }

    public static void main(String[] args) {
        // 複数DBに接続を確立
        DataSource ds1 = getDataSource("ds1", "jdbc:mysql://localhost:3306/test_database1", "test_username", "test_password");
        DataSource ds2 = getDataSource("ds2", "jdbc:mysql://localhost:3306/test_database2", "test_username", "test_password");

        // トランザクションマネージャーの取得
        UserTransaction utx = TransactionManagerServices.getTransactionManager();

        try {
            // トランザクション開始
            utx.begin();

            try (Connection conn1 = ds1.getConnection();
                 PreparedStatement pstmt1 = conn1.prepareStatement("INSERT INTO your_table (column1) VALUES (?)");
                 Connection conn2 = ds2.getConnection();
                 PreparedStatement pstmt2 = conn2.prepareStatement("INSERT INTO your_table (column2) VALUES (?)")) {

                pstmt1.setString(1, "value1");
                pstmt1.executeUpdate();

                pstmt2.setString(1, "value2");
                pstmt2.executeUpdate();

                // コミット
                utx.commit();
                System.out.println("Transaction committed successfully");

            } catch (SQLException e) {
                utx.rollback();
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

RowSetを使用したデータ操作

RowSetはデータベースの行セットを操作するためのオブジェクトで、特にオフラインでのデータ操作に便利です。
以下は、RowSetの使用例です。

Mavenの依存関係

pom.xmlに以下の依存関係を追加します。

<dependency>
    <groupId>com.sun.rowset</groupId>
    <artifactId>com.suns.rowset</artifactId>
    <version>1.0.1</version>
</dependency>
コード例
import com.sun.rowset.CachedRowSetImpl;

import javax.sql.RowSet;
import java.sql.SQLException;

public class RowSetExample {
    public static void main(String[] args) {
        try (RowSet rowSet = new CachedRowSetImpl()) {
            // DBに接続
            rowSet.setUrl("jdbc:mysql://localhost:3306/test_database");
            rowSet.setUsername("test_username");
            rowSet.setPassword("test_password");
            rowSet.setCommand("SELECT * FROM your_table");
            rowSet.execute();

            // 一行ずつ処理
            while (rowSet.next()) {
                String column1 = rowSet.getString("column1");
                String column2 = rowSet.getString("column2");
                System.out.println(column1 + ", " + column2);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

これらのコード例を使用することで、javax.sqlパッケージを活用した高度なデータベース接続管理機能を実装できます。