📘 Vol.10.2：DAOのインタフェース設計と実装パターン （※DTO設計の次に押さえるべきDAO層の設計と実装パターンを完全解説）

### 🧭 目次
- 1.DAO層とは？アーキテクチャ上の役割

- 2.DAOインタフェースと実装の分離（＋マッピング処理の設計）

- 3.DAOの責務と粒度の考え方

- 4.DAO層でよくあるアンチパターンとその改善策

- 5.まとめ・次回予告

---

### 🧩 1. DAO層とは？アーキテクチャ上の役割
- DTOが「データ構造」なら、DAOは「永続化ロジック」の責任を持つ

- DB操作のロジックをActionやService層に持たせないことで、責務分離を徹底

- 主な役割：
  - SQLの発行と実行

  - DTOとのデータマッピング

  - トランザクション制御（複数DAOが絡む場合はService層へ）

---

### 🧩 2. DAOインタフェースと実装の分離

### ✅ 実装の基本構造

```java
// UserDao.java（インタフェース）
public interface UserDao {
    User findById(int userId);
    List<User> findAll();
    void insert(User user);
    void update(User user);
    void delete(int userId);
}

// UserDaoImpl.java（実装）
public class UserDaoImpl implements UserDao {
    public User findById(int userId) {
        // DB接続、SQL実行、マッピング処理
    }
    // その他実装...
}
```

### ✅ なぜインタフェースと分離するのか？
- 実装の切り替えを柔軟に（MockDao、JdbcDao、JpaDaoなど）

- テストやDI（依存性注入）との親和性向上

### ✅ ResultSet → DTO のマッピング処理

```java
public User mapToUser(ResultSet rs) throws SQLException {
    User user = new User();
    user.setUserId(rs.getInt("user_id"));
    user.setUsername(rs.getString("username"));
    user.setEmail(rs.getString("email"));
    return user;
}

```

- mapToUser() のようなマッピング処理は 専用メソッドに切り出す

- 複数DAOで共通化できる処理は、BaseDao のような親クラスにまとめるのもアリ

---

### 🧩 補足：ResultSet → DTO マッピング処理は分離するのがベストプラクティス

DAO 実装クラスの中で頻出する「ResultSet → DTO への変換」処理は、専用のマッピングクラスに分離するのがベストプラクティスです。以下のように切り出すことで、責務が明確になり、再利用性も高まります。

#### ✅ 実装例：UserMapper クラスに分離

```java
// UserMapper.java
public class UserMapper {
    public static User map(ResultSet rs) throws SQLException {
        User user = new User();
        user.setUserId(rs.getInt("user_id"));
        user.setUsername(rs.getString("username"));
        user.setEmail(rs.getString("email"));
        return user;
    }
}
```
DAO の中ではこのように呼び出します：
```java
// UserDaoImpl.java
public class UserDaoImpl implements UserDao {
    public User findById(int id) {
        try (Connection conn = ..., PreparedStatement stmt = ...) {
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return UserMapper.map(rs); // ✅ マッパークラスで変換
            }
        } catch (SQLException e) {
            ...
        }
        return null;
    }
}
```

✅ なぜ分離するのか？
- DAO の役割は「SQLを実行してDTOに渡す」までに限定したほうがよい

- ResultSet → DTO の変換処理は、マッピングロジックとして切り離すと可読性・保守性が向上する

- 複数DAOで同じDTOを扱う場合も、共通のMapperを使い回せる

✅ より高度な設計に発展可能
- 全DAOで使える汎用的な BaseMapper<T> インタフェースの定義

- Java 8 以降であれば、ラムダ式 + 関数型インタフェース化も可能（例：Function<ResultSet, User>）

設計の柔軟性を高めるためにも、こうしたマッピングの責務分離はぜひ検討したいポイントです。

---

### 🧩 3. DAOの責務と粒度の考え方
### ✅ DAOの責務
- 1DAO = 1テーブル操作が基本

- 複雑なJOINや業務ロジックはDAOではなくService層へ分離

### ✅ 粒度のバランス感覚

| よくある誤り                | 改善指針                                             |
| --------------------- | ------------------------------------------------ |
| UserDaoに全てのユーザー系機能を書く | `UserDao`, `UserRoleDao`, `UserSettingDao` などに分割 |
| SQLが長大で可読性が悪い         | ViewやStored Procedure、Repositoryパターンの活用を検討       |

---

### 🧩 4. DAO層でよくあるアンチパターンとその改善策

| アンチパターン             | 問題点          | 改善策                   |
| ------------------- | ------------ | --------------------- |
| SQLをActionクラス内に直接書く | 責務の混在、再利用性低下 | DAO層に委譲する             |
| ResultSetの直接操作を繰り返す | コピペ地獄、バグ温床   | マッピング共通化・専用メソッドの活用    |
| 例外を握りつぶす            | 原因特定不能       | 適切にスロー or ログ記録        |
| 1DAOで複数テーブルを操作      | 単一責務原則に反する   | DAOを分割し、Service層で統合制御 |


---

### 📌 まとめ
- DAOは「DB操作に責任を持つ層」であり、DTOと密接に連携

- 実装クラスは可能な限りマッピング処理を切り出し、再利用性と保守性を高める

- 粒度設計と責務分離を意識することで、大規模化にも耐えられる設計に

---

### ▶️ 次回予告
### 📘 Vol.10.3：DB接続クラスの共通化とドライバ設計

- ConnectionManager の共通化

- トランザクション管理戦略

- JDBCドライバの初期化と設定管理 などを扱います！

---

### ✨ シリーズまとめ（Vol.10.x バリデーション編）

- [✅ Vol.10.0：DAO / DTO / JavaBeansとは？ ― データ層設計の全体像と役割分担 ―](https://qiita.com/drafts/19c1d526df28240e0cb1/edit)

- [✅ Vol.10.1：DTO設計のベストプラクティス（命名規則・フィールド設計](https://qiita.com/juehara-crypto/items/1b0ad616095f8ae134ec)

- [✅ Vol.10.3：DB接続クラスの共通化とドライバ設計](https://qiita.com/juehara-crypto/items/c3d4e8e6887d5ec8e1eb)

- [✅ Vol.10.4：Actionとの連携実装（Struts2との融合）](https://qiita.com/juehara-crypto/items/b8873de1aa9e46cd9309)

- [✅ Vol.10.5：DAO・DTOのテスト設計（JUnitやH2活用）](https://qiita.com/juehara-crypto/items/9f0914697726068b9e93)

- [✅ Vol.10.6：Service層の設計方針と例外処理戦略 ](https://qiita.com/juehara-crypto/items/6685c303c40e48b3c1f3)

- [✅ Vol.10.7：Service層×JUnitテストの基本とパターン](https://qiita.com/juehara-crypto/items/128fda40df3ffa0fedce)

- [✅ Vol.10.8：Service層の共通基盤化とDI対応 ](https://qiita.com/juehara-crypto/items/8e94acf2a31be15aaf94)

---