【JavaGold】JDBCによるデータベース連携

# JDBC
DBMSとの連携時に発生する例外クラスが提供されている。


JDBCを利用してデータベースを接続するためのURL
```
jdbc:DBMS名://<サーバーのIPアドレス>：<ポート番号>/データベースの場所
```
```:例題
jdbc:mysql://localhost/test
jdbc:postgresql://localhost：5432/test
```

### java.sql.DriverManager

#### getConnection()
JDBCを利用してデータベースを接続するクラス、メソッド

### java.sql.Connection
#### close()
DBMSと接続を解除するためのメソッド

#### prepareStatement()
```java:実装例
PreparedStatement ps = con.prepareStatement("select * from emp")
```

### java.sql.Statement
SQL文をそのままDBMSに渡す。

```java:実装例
public class Sample {
    public static void main (String[] args) {
        try {
            // 入力した情報をもとにSQL文を作成する
            String sql = "select * from item";
            // Statementオブジェクトを取得する
            Statement st = con.createStatement();
            // SQL文を実行する
            int ret = st.executeUpdate(sql);
        } catch(Exception e) {
            //例外の状態を出力する
            e.printStackTrace();
        }  
    }
}
```

#### `executeBatch()`
一度に複数のSQL文を実行。

#### `enquoteIdentifier​(String identifier, boolean alwaysQuote)`
指定された文字列に対し、HiRDBのSQL記述での名前の指定に可能な文字列か判定し，元の値の文字列又は二重引用符で囲まれた文字列を返します。

* enquoteIdentifierを使用することによってSQLインジェクションを防ぐ一定の効果がある。

※SQLインジェクションとは、第三者がSQLコマンドを悪用してデータベースの情報へ不正にアクセスし、情報を搾取や改ざん、削除する攻撃手法

```java:実装例
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class Sample {
    public void execute(Connection con, String name) throws SQLException {
    Statement stmt = con.createStatement();
    String sql = "SELECT * FROM TABLE WHERE NAME =" + stmt.enquoteIdentifier(name, true);
    stmt.execute(sql);
}
```

### java.sql.PreparedStatement
事前にコンパイルしてからDBMSにSQL文を渡す。

#### executeUpdate()
データの挿入、更新、削除に使用。
何件更新されているか調べる時に使用。

PreparedStatementオブジェクトを取得する方法
```java:実装例
var sql = "delete from item where id = ?";
try (var ps = con.preparedStatement(sql)) {
    ps.setInt(1, 1);
    ps.executeUpdate();
}
```

setXXX形式で値をセットする。
第1引数に渡すのは「1から始まる番号」

#### executeQuery()
データを検索するのに使用。

```java:実装例
import java.sql.Connection;
﻿﻿﻿import java.sql.DriverManager;
﻿﻿﻿import java.sgl.PreparedStatement;
import java.sql.ResultSet; 
import java.sql.SQLException;

public class Sample {
    public static void main (String[] args) {
        try (Connection con = DriverManager. getConnection (
                "jabc: derby: //localhost: 1527/data/Sample")) {
                
            var sql = "select * from item";
                try (PreparedStatement ps = con.prepareStatement(sql)) {
                    ResultSet rs = ps.executeQuery();
                    while (rs.next()) {
                        System.out.print(rs.getInt(1) + ":");
                        System.out.println(rs.getString("name"));

                    }
                }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
```
nextメソッドを一度も呼び出さなかった場合、どの行も選択されていないことになる。
行が選択されていない状態でgetXXXメソッドを呼び出すと、例外がスローされる。

#### execute()
boolean値を返す。

#### ストアドプロシージャの呼び出し
```java
import java.sgl.CallableStatement;
﻿﻿﻿import java.sql.Connection;
﻿﻿﻿import java.sgl.DriverManager;
﻿﻿﻿import java.sgl.SQLException;

public class CallSample { 
    public statie void main(String[] args) {
        try (Connection con = DriverManager.getConnection(
                "jabe: derby: //localhost: 1527/data/Sample")) {

            String proc = "CALL UPDATE _ITEM(?, ?)";
            try (CallableStatement cs = con.prepareCall(proc)) {
                cs.setString(1, "call procedure");
                cs.setInt (2, 1);
                cs.execute();
            }
        } catch (SQLException e) {
            throw new RuntimeException (e);
        }
    }
}
```