0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java JDBC

Last updated at Posted at 2025-04-16

JavaGoldの資格取得のためにアウトプットかつ、備忘録のための記事です。
誤り等、わかりずらい等があればご指摘お願いいたします:bow_tone3:

JDBCを使用したデータベース接続

内容
・JDBCを使用したデータベース接続
・SQLステートメントの実行
・ResultSetの拡張

JDBCとは

JDBCとは、Javaプログラムからデータベースにアクセスするための共通インタフェース。
使用するパッケージは以下
java.sql:データベースに格納されたデータへアクセスして処理する基本APIを提供。
javax.sql:データベースにアクセスする際、サーバー側での処理(接続プールや分散トランザクション等)を行う場合に使用するAPI

データベースにアクセスするクラスは、共通インタフェースとして提供されているJDBC APIを使用することで、接続するデータベース製品の違いを意識することなく実装できる。

JDBCドライバ

JDBCドライバはJavaプログラムとデータベースを紐づけるために必要なJDBCインタフェースを実装したクラス。

基本的なJDBCアプリケーションの作成

JDBCを使用するときの一般的な流れ

流れ
1:java.sqlパッケージのインポート
      ↓
2:データベースの指定
      ↓
3:データベースとの接続
      ↓
4:ステートメントの取得
      ↓
5:SQL文の実行
      ↓
6:結果の取得と処理
      ↓
7:接続のクローズ

また、java.sqlパッケージで提供されている主なクラス、インタフェースは以下↓
DriverManagerクラス:データベースのドライバを管理し、データベースとの接続を支援する。
Connectionインタフェース:特定のデータベースとの接続(セクショ)を表現する。
Statementインタフェース:静的SQL文を実行し、作成された結果を返すために使用さるオブジェクト。
ResultSetインタフェース:データベースの結果セットを表すデータオブジェクト。

JDBCの使用例
		Connection con = null;
		Statement stmt = null;
		ResultSet rst = null;
		
		try {
			// 2:データベース指定
            // 指摘修正
			//String url = "jdbc:mysql//○○";
            String url = "jdbc:mysql://<hosts>/<database>"; 
			
			// 3:データベースとの接続
			con = DriverManager.getConnection(url, "root", "training");
			
			// 4:ステートメントの取得
			stmt = con.createStatement();
			
			// 5:SQL文の実行
			String sql = "select * from department";
			rst = stmt.executeQuery(sql);
			
			// 6:結果の取得と処理
			while(rst.next()) {
				System.out.println("dept_code : " + rst.getInt(1));
				System.out.println("dept_name : " + rst.getString(2));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 7:接続のクローズ
			try {
				if (rst != null) rst.close();
				if(stmt != null) stmt.close();
				if (con != null) con.close(); 
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

解説
2:データベース指定
通信先のデータベースを特定するためのJDBC URLをも実で準備している。
URLの構文は以下の通り。
プロトコル、サブプロトコル、サブネーム名を含み、:で区切る

JDBC URLの構文
jdbc:<subprotocol>:<subname>

3:データベースとの接続
データベース接続をするにはDriverManagerクラスgetConnection()メソッドを呼び出し、Connectionオブジェクトを取得する。
以下がDriverManagerクラスの主な接続用メソッド
static Connection getConnection(String url) throws SQLException
 ┗指定されたデータベースのURLへの接続を試みる

static Connection getConnection(String url, String user, String password) throws SQLException
 ┗指定されたデータベースのURLへ、ユーザー名・パスワードを使用して接続を試みる

ConnectionObjectを取得できなかった場合は、SQLException例外がスローされる

4:ステートメントの取得
標準的な問い合わせを実行するには、Statementオブジェクトを使用する。
StatementオブジェクトによりSQLコマンドを実行する。Statemntオブジェクトは、Connectionインタフェースの`createStatement()メソッド'で取得する。

5:SQL文の実行
SQL文を文字列でまず用意する。
Statementインタフェースのメソッドを使用してSQL文を実行する。
今回はSELECT文なので、executeQueryを使用する。

6:結果の取得と処理
executeQueryの実行によって、ResultSetオブジェクトとして検索結果が返される。
ResultSetオブジェクトは、問い合わせにより返されたデータを表し、1行ずつ処理ができる。
ResultSetオブジェクトから値を取り出すには以下のように列・行にアクセスする。
・行へのアクセス
next()メソッドにより、1行ずつデータを取り込む。
next()メソッドは、1行ずつデータにアクセスし、次の行があればtrueを返す
ResultSetオブジェクト生成時は、カーソルが先頭行の前にあるため、必ず一回はnext()メソッドを実行しないと行を取り出すことはできない。
next()を一回も呼び出さずにデータの取り出しを試みるとSQLExceptionが発生する

・列へのアクセス
getterメソッドで引数に列番号を指定することによりデータを取り出せる。
列番号はResultSetオブジェクト内の左から右へ順に降られた番号で、最初の列は1。
また、列名を指定して取り出すこともできる。
getterメソッドでは、getXXX(列名) もしくはgetXXX(列番号) というメソッド名が定義されており、XXXの部分にはJavaのデータ型名が入る。

7:接続のクローズ
すべての処理が終了したらリソースの解放をす。
Connectionインタフェース、Statementインタフェース、ResultSetインタフェースは使用したリソースを解放するためにclose()メソッドを提供している。

例外

Javaアプリケーションがデータベースと通信した時に発生するエラーはデータベースからアプリケーションへ通知される。エラーの通知にはSQLExceptionオブジェクトが使用される。
発生する理由は様々。
例↓
・ネットワークケーブルが物理的な問題により通信が切断した。
・SQLコマンドのフォーマットが不適切である。
・サポートされていない機能を使用。
・存在しない列を参照した。

SQLExceptionクラスのメソッドを使用して、エラーメッセージを取得することができる。
主なクラス↓
int getErrorCode()
ベンダ固有の例外コードを取得する。

String getSQLState()
SQLStateを取得する。

SQLステートメントの実行

JDBCでは3種類のステートメントを使用できる。
インタフェースとして提供される。
Statement:標準的なSQL文を実行
PreparedStatement:プリコンパイルされたSQL文を実行
CallableStatement:ストアドプロシージャを実行

Statementインタフェース

標準的な問い合わせを実行するには、ConnectionインタフェースのcreateStatementメソッドからStatementオブジェクトを取得する。

Statementインタフェースの主なメソッド
ResultSet executeQuery(String sql) throws SQLException
単一のResultSetオブジェクトを返す指定されたSQL文を実行する。
該当するレコードがない場合でもnullにはならない。

int executeUpdate(String sql) throws SQLException
指定されたSQL文を実行する。SQL文はデータ操作言語文(INSERT,UPDATE,DELETE)、あるいは、DDL文のような何も返さないSQL文を指定する。
戻り値は、引数がDML文の場合は、行数を返す。何も返さないSQL文の場合は0を返す。

boolean execute(String sql) throws SQLException
SQL文の実行結果がResultSetオブジェクトの場合はtrueを、更新行数または結果がない場合はfalseを返す

SELECT - executeQuery()メソッドで問い合わせ

executeQueryメソッドの使用例
		String sql = "select * from department where dept_code = " + args[0];
		
		try(Connection con = DBConection.connection();
				Statement st = con.createStatement();
				ResultSet rst = st.executeQuery(sql)) {
			
			if(rst != null) System.out.println("rs != null");
			while(rst.next()) {
				System.out.println("dept_name : " + rst.getString("dept_name"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

INSERT - executeUpdateメソッドで問い合わせ

executeUpdateメソッドによるINSERT処理
		String sql = "INSERT INTO department values " + "(6,'planning', 'Yokohama', '000-0000-0000')";
		try(Connection con = DBConection.connection();
				Statement st = con.createStatement();) {

            // 指摘修正
			// int col = st.executeUpdate(sql);
            int row = st.executeUpdate(sql);
			
			System.out.println("col : " + col);
		} catch (Exception e) {
			e.printStackTrace();
		}

UPDATE - executeUpdateメソッドで問い合わせ

executeUpdateによるUPDATE処理
		String sql = "update department set dept_address = 'Tokyo' where dpt_code = " + args[0];
		
		try(Connection con = DBConection.connection();
				Statement st = con.createStatement();) {
			
			int col = st.executeUpdate(sql);
			
			System.out.println("col : " + col);
		} catch (Exception e) {
			e.printStackTrace();
		}

更新できた件数を返す。

DELETE - executeUpdate()メソッドで問い合わせ

executeUpdateメソッドによるDELETE処理
		String sql = "delete from department where dpt_code = " + args[0];
		
		try(Connection con = DBConection.connection();
				Statement st = con.createStatement();) {
			
			int col = st.executeUpdate(sql);
			
			System.out.println("col : " + col);
		} catch (Exception e) {
			e.printStackTrace();
		}

execute()メソッドでSQL文の実行

一般的には検索処理文の実行にはexecuteQuery(),更新処理文の実行にはexecuteUpdate文を使用するが、どっちの処理でも実行可能なメソッドとしてexecute() が提供されている。
引数には、検索/更新いずれの処理文が指定可能。
処理内容によって戻り値が違うので、戻り値の型はboolean型になっている。
ResutlSetオブジェクトが返ってきている場合は、true
更新行もしくは結果がない場合は、falseが返却される。
以下は結果を取り出すStatementインタフェースのメソッド↓
ResultSet getResutlSet() throw SQLException
┗ ResultSetオブジェクトを取得する

int getUpdateCount throws SQLException
┗ 更新行数を取得する。

execute()メソッドの利用
		String[] sqls = {
				"insert into department values (7, 'planing', 'Yokohama', '000-0000-0000')",
				"select dept_name from department where dept_code = 2"
		};
		
		try(Connection con = DBConection.connection();
				Statement st = con.createStatement();) {
			
			for(String sql : sqls) {
				boolean isResultSet = st.execute(sql);
				if (isResultSet) {
					ResultSet rs = st.getResultSet();
					rs.next();
					System.out.println(rs.getString(1));
				}else {
					int count = st.getUpdateCount();
					System.out.println(count);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

executeXXXメソッドの特徴

以下の通り↓
execute(String sql)
戻り値:boolean
ture :ResultSetオブジェクトの取得が可能
false:更新行の取得が可能 or 結果がない

executeQuery(String sql)
戻り値:ResultSet
結果の取得には一回はnext()を呼ばないといけない。
該当コードがない場合でも、ResultSetはnullにはならない

executeUpdate(String sql)
戻り値:int
更新行が返る。
更新した行がなかった場合は0が返る。

ResultSetの拡張

ResultSetオブジェクトの高度な機能

ResultSetオブジェクトでは以下のような機能を使用できる。
・問い合わせ結果のスクロール、絶対/相対位置特定
・ResultSetオブジェクト上でデータの挿入・更新

スクロール機能や更新処理が可能なResultSetオブジェクトを取得するには、各ステートメントの取得時に、ResultSetインタフェースで提供されている定数を指定する。

以下がResultSetインタフェースで定義されている定数
CONCUR_READ_ONLY:更新できないResultSetオブジェクトの並行処理モードを示す
CONCUR_UPDATABLE:更新できるResultSetオブジェクトの並行処理モードを示す
TYPE_FORWARD_ONLY:カーソルが順方向にしか移動しないResultSetオブジェクトを示す
TYPE_SCROLL_INSENSITIVE:スクロール可能だが、データベースのデータに対して行われた変更を反映しないResultSetオブジェクトのタイプを示す
TYPE_SCROLL_SENSITVE:スクロール可能でデータベースの最新の内容を反映するResultSetオブジェクトのタイプを示す

問い合わせ結果のスクロール、絶対/相対位置指定

Statementオブジェクトを使用して、スクロール可能なResultSetオブジェクトを取得する
次のコード例はStatementオブジェクトを取得する際に、ResultSetインタフェースの定数を指定している

コード例
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

createStatement()メソッドの第一引数に、TYPE_SCROLL_INSENSITIVEもしくはTYPE_SCROLL_SENSITVEを指定することで、ResultSetオブジェクト内を順方向or逆方向に移動できる。
第二引数には、CONCUR_UPDATABLEを指定することで取得したResultSetオブジェクトを通じてレコードの挿入や更新、削除を行うことができる。
スクロール可能なResultSetオブジェクトでは、next()メソッド以外にもカーソルを任意に移動するメソッドを使用できる。
以下、ResultSetインタフェースのカーソル移動用メソッド↓
boolean absolute(int row) throws SQLException
┗ カーソルをこのResultSetオブジェクト内の指定された行番号に移動する。

boolean relative(int row) throws SQLException
┗ カーソルを正または、負の相対行数だけ移動する

boolean next() throws SQLException
┗ カーソルを現在位置から1行順方向に移動する

boolean previous() throws SQLException
┗カーソルをこのResultSetオブジェクト内の前の行に移動する

boolean first() throws SQLException
┗ カーソルをこのResultSetオブジェクト内の先頭の行に移動する

boolean last() throws SQLException
┗ カーソルをこのResultSetオブジェクト内の最終行に移動する

void afterLast() throws SQLException
┗ カーソルをこのResultSetオブジェクト内の最終行の直前に移動する

void beforeFirst() throws SQLException
┗ カーソルをこのResultSetオブジェクト内の先頭行の直前に移動する

int getRow() throws SQLException
┗ 現在の行番号を取得する。最初の一行は1となる

指摘修正

1:2024-04-18

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?