【備忘録】JavaとDBの連携（基礎）

自分用に備忘録兼やったことを残していこうかなと。基本的なことばかりですが、、
間違っている点、改善したほうが良い点あったら、ご指摘いただければ幸いです。

**環境**
Java 8
MySQL ver 8.0.14

#基本的なコード
Statementではなく、PreparedStatementクラスを使用する。
sql injection防止の為。

```java
package dbAccess;

import java.sql.*;
import java.util.Scanner;

public class DbAccess_pres_select {
	public static void main(String[] args) {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
           /* DB_HOST:DB_PORT/DB_NAMEの3つは各自設定 
　　　　　　mysql 8からドライバーのタイムゾーンのエラーが出てしまう為、以下のように記述*/
			Connection con = DriverManager.getConnection(
				"jdbc:mysql://DB_HOST:DB_PORT/DB_NAME?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC",
				"hogeuser",
				"Password"
			);
			String line = new Scanner(System.in).nextLine();

			String sql = "SELECT * FROM employee WHERE nm_employee = ?";

			PreparedStatement stmt = con.prepareStatement(sql);

			// 1は?の数と場所を示している。
			stmt.setString(1, line);

			// executeQueryはResultSet型を返す。検索用メソッド
			ResultSet rs = stmt.executeQuery();

			while (rs.next()) {
				int id = rs.getInt("id");
				String name =rs.getString("name");
				String kana = rs.getString("kana");
				String email = rs.getString("mail");
				String pass = rs.getString("password");
				int idDep = rs.getInt("id_department");

				System.out.println(id + "\t" + name + "\t" + kana +"\t" + email + "\t" + pass + "\t" + idDep);
			}

			stmt.close();
			con.close();
		} catch(ClassNotFoundException e) {
			e.printStackTrace();
		} catch(SQLException e) {
			e.printStackTrace();
		}
	}
}
```

#SELECT以外のDML(INSERT, UPDATE, DELETE)の場合
`executeUpdate()`メソッドを使用する。
戻り値はint型。更新した数を戻す。

```java
// 省略
int i = ps.executeUpdate();
System.out.println("更新数：" + i);
```

#その他もろもろ
~~StatementやConnectionの取得、切断はUtilクラスか何かを作ってその中でstaticメソッドとして記述する。Mainクラスで利用。~~
=> 1人しか利用しないスタンドアロン環境であれば問題ないが、サーバサイドで運用する場合はConnectionの大量生成を抑えるためにコネクションプールを使う。（スタンドアロン環境でもできるだけ毎回コネクションを作るようにする。）
`nkojimaさん`コメントありがとうございます！

```java:DbUtil.java
import java.sql.*;

public class DbUtil {
	private static final Stringで8つを定義しておく
   "ホスト名の値やローカルサーバのIPアドレス";
   "database名";
   "user名";
   "password";
   "mysql"; // 使用するDB
   "com." + DBMS + ".cj.jdbc.Driver"; // ドライバー
   "ポート番号";
   "jdbc:" + DBMS + "://" + DB_HOST + ":" + DB_PORT + "/" + DB_NAME + "?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC"; // DBのURL

	// インスタンス化の禁止
	private DbUtil() {
	}

	// Connectionを単一のインスタンスとする
　　　// 複数のアプリケーションから取得される場合はコネクションプールを利用するなどする。
	private static Connection con;

	// コネクションを取得
	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		if (con == null || con.isClosed()) {
			Class.forName(DB_DRIVER);
			con = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
		}
		return con;
	}
	
        // ステートメントを切断
	public static void closeStatement(PreparedStatement stmt) throws SQLException {
		if (stmt != null) {
			stmt.close();
		}
	}

	// コネクションを切断
	public static void closeConnection(Connection con) throws SQLException {
		if (con != null) {
			con.close();
		}
	}
}
```

#DAOとDTO
**DAO**クラスには

- コンストラクタ（DAOインスタンス生成時に引数にDBコネクションを指定）

```java
public EmployeeDAO(Connection con) {
		this.con = con;
}
```

- DTO型のリストを返す`SELECT`,`INSERT`,`UPDATE`,`DELETE`メソッドを記述

```java
public List<EmployeeDTO> selectAll() throws SQLException, ClassNotFoundException {
	/* リターン用のListを宣言、初期化 */
        /* sql文 */
		try {
			/* sql文を実行し、Listに格納 */
		} finally {
			/* statementをクローズ */
		}
		return rtnList;
	}
public List<EmployeeDTO> empInsert(挿入したいデータ分の引数) throws 例外いろいろ {
// その他メソッド（UpdateやDelete）
```

**DTO**クラスには

- DBのテーブルのカラムをフィールドとして設定。

```java
public class EmployeeDTO {
	/** 社員ID */
	private int idEmployee;
	/** 社員名 */
	private String nmEmployee;
	/** 社員名カナ */
	private String knEmployee;
	/** メールアドレス */
	private String mailAddress;
	/** パスワード */
	private String password;
	/** 役職ID */
	private int idDepartment;
```

- 必要に応じて各getter, setterを作成する。

```java
/* 一例 */
public int getIdEmployee() {
	return idEmployee;
}
public void setIdEmployee(int idEmployee) {
	this.idEmployee = idEmployee;
}
```