sql箇所のログの出力メモ(java)

## はじめに
javaでsql箇所のログを出力するセットにおいて、
ログ出力の導入イメージをメモっておきます。

## 環境構築
MavenやGradleのビルドツールは使用していません。
手動でセットし、Eclipseを使用しています。

UdemyでJavaに定評のあるサーチマン佐藤さんのJavaシリーズVol.4【JavaからDB接続】MVCモデルでBeans+DAOを使って、WebアプリのDBを覚える。を使用させて頂きました。
https://www.udemy.com/course/javavol4/?couponCode=BFCPSALE24JP

## 対応手順 
Eclipseを使用している前提で説明します。
**1. ログライブラリを探す**
**2. ライブラリの導入**
**3. Logback の設定**
**4. ログの記録コードを追加**
**5. Eclipseで実行**

## 1. ログライブラリを探す

### ログ取得で利用できるライブラリー例

一般的に、Javaでは以下のようなライブラリを使ってログを記録します。

- **SLF4J** + **Logback**（おすすめ）
- **java.util.logging**（標準ライブラリ）
- **Apache Log4j 2**

ここでは、`SLF4J` と `Logback` を使用する例を示します。


## **2. ライブラリの導入**
#### **手動で JAR ファイルを追加する場合**
中央リポジトリのWebサイト [Mavenリポジトリ](https://mvnrepository.com/) でライブラリーを検索。
1. `slf4j-api` と `logback-classic`、`logback-core`をダウンロードします。
2. Eclipseプロジェクトに `lib` フォルダを作成し、ダウンロードした JAR を配置します。
3. 右クリックでプロジェクトに JAR をビルドパスとして追加します。
 
  - 例えば、以下のURLで直接ファイルを探せます：
    - SLF4J API: https://mvnrepository.com/artifact/org.slf4j/slf4j-api
    - Logback: https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
    - logback-core: https://mvnrepository.com/artifact/ch.qos.logback/logback-core

#### **Maven プロジェクトの場合**
今回は手動でセットしますが、Mavenの場合、依存関係を `pom.xml` に追加します。

```xml
<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.11</version>
    </dependency>
</dependencies>
```


## **3. Logback 設定ファイルを作成**
`src/main/resources` または `src` ディレクトリに `logback.xml` を作成します。

#### **logback.xml サンプル**
```xml
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
```
**2**でダウンロードしたjarファイル、上記でセットするlogback.xmlのフォルダ構成は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176603/4b91bdf3-b46f-722f-f95d-9c6146efe18a.png)



## 4. ログの記録コードを追加

`dao` パッケージにある `ShainDAO.java` を例にします。

#### **ShainDAO のコード例**
```java
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import beans.ShainBean;

public class ShainDAO extends ConnectionBase {
    // Loggerの初期化
    private static final Logger logger = LoggerFactory.getLogger(ShainDAO.class);

    /**
     * 社員IDから社員Beanを取得
     * @param con Connection
     * @param shain_id 社員ID
     * @return ShainBean 社員Bean
     * @throws SQLException
     */
    public ShainBean getShain(Connection con, String shain_id) throws SQLException {
        // 社員Beanの初期化
        ShainBean shainBean = new ShainBean();

        // 社員IDで取得するSQL
        final String sql = "select shain.id, shain.name, bu.name, shain.enter_date "
                + "from shain_master shain, bu_master bu where shain.bu_id = bu.bu_id and shain.id=?";

        // SQL実行の準備
        try (PreparedStatement stmt = con.prepareStatement(sql)) {
            // パラメータを設定
            stmt.setString(1, shain_id);

            // SQLのログ出力
            logger.debug("Executing SQL: {}", stmt);

            // SQL実行
            try (ResultSet rs = stmt.executeQuery()) {
                // SQLで結果があれば
                if (rs.next()) {
                    // 一行目の値を取得
                        //省略
                    // 取得した値を社員Beanにセット
                    　　//省略
                }
            }
        } catch (SQLException e) {
            logger.error("SQL execution error: {}", e.getMessage(), e);
            throw e;
        }

        return shainBean;
    }

    /**
     * 全社員を取得
     * @param con Connection
     * @return ArrayList<ShainBean> 社員リスト
     * @throws SQLException
     */
    public ArrayList<ShainBean> getAllShain(Connection con) throws SQLException {
        // ArrayListの初期化
        ArrayList<ShainBean> shainList = new ArrayList<>();

        // 社員全件取得SQL
        final String sql = "select shain.id, shain.name, bu.name, shain.enter_date "
                + "from shain_master shain, bu_master bu where shain.bu_id = bu.bu_id";

        // SQL実行の準備
        try (PreparedStatement stmt = con.prepareStatement(sql)) {
            // SQLのログ出力
            logger.debug("Executing SQL: {}", stmt);

            // SQL実行
            try (ResultSet rs = stmt.executeQuery()) {
                // 取得した行数を繰り返す
                while (rs.next()) {
                    // 社員Beanの初期化

                    // 値を取得

                    // 取得した値を社員Beanにセット

                    // リストに社員Beanを追加

                }
            }
        } catch (SQLException e) {
            logger.error("SQL execution error: {}", e.getMessage(), e);
            throw e;
        }

        return shainList;
    }
}

```

## 5. Eclipseで実行
1.TestShainDAO.javaを実行します
```TestShainDAO.java
package test;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;

import beans.ShainBean;
import dao.ShainDAO;

public class TestShainDAO {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		try (Connection con = ShainDAO.getConnection();) { //DB接続

			//社員DAO初期化
			ShainDAO shainDao = new ShainDAO();
			/**ShainDAO.getShainのテスト*/
			//社員ID
			String shain_id = "0001";
			//社員Beanの取得
			ShainBean shainBean = shainDao.getShain(con, shain_id);

			//社員Beanのテスト結果（値を取得し、表示する）
            //省略

			/**ShainDAO.getAllShainのテスト*/
			ArrayList<ShainBean> shainList = new ArrayList<ShainBean> ();

			//全社員Beanの取得
			shainList = shainDao.getAllShain(con);

			//全社員Beanのテスト結果（値を取得し、表示する）
            //省略
			
		} catch (SQLException | ClassNotFoundException e) {
		e.printStackTrace();
		}	
	}
}

```

2. コンソールにログが出力されます。
 
```
20:52:31.308 [main] DEBUG dao.ShainDAO -- Executing SQL: com.mysql.cj.jdbc.ClientPreparedStatement: select shain.id, shain.name, bu.name, shain.enter_date from shain_master shain, bu_master bu where shain.bu_id = bu.bu_id and shain.id='0001'
20:52:31.309 [main] DEBUG dao.ShainDAO -- Executing SQL: com.mysql.cj.jdbc.ClientPreparedStatement: select shain.id, shain.name, bu.name, shain.enter_date from shain_master shain, bu_master bu where shain.bu_id = bu.bu_id

```

## 参考
https://qiita.com/kero3/items/0033adca07a585623768