JavaBeansとDao

## JavaBeans
Javaにおいてデータをひとつにまとめて格納するために利用する仕組みを指し、データベースから取得した値を格納する。

JavaBeansの設計ルールに従って作られたクラスを**Bean**と呼びユーザーが入力した内容をサーバーへ送信したり、データベースに保存したりする際、それらのデータをひとつの「Bean」として定義することで扱いやすくなる。
＊エンティティやDTOとも呼び、それぞれ細かい違いがあるが大枠の内容は一緒

### JavaBeansの設計ルール
**①クラスをpublicで宣言する**
**②引数なしのpublicコンストラクタを作成する**
Javaのオブジェクトにはコンストラクタが必要なので引数のない空のコンストラクタを作成する
引数なしにインスタンスを生成できるということは、後述の「シリアライズ」を行う上で重要な意味合いをもつ。
フレームワークでは、自動でJavaBeansを作成するような機能をもっているのものが多く、フレームワークはJavaBeansのルールに基づき、「引数なしのコンストラクタ」を利用してJavaBeansを生成する

**③java.io.Serializableを実装する**
Serializableを実装することで、「シリアライズ」できるようになる
シリアライズとは直訳すると「直列化」という意味で、Javaにおいては外部との通信やデータ保存に利用できるような仕組みを指す。
Serializableインターフェースを実装することで通信に利用できるようになり、JSPでの利用やセッションへの格納が可能となる

**④パッケージ化する**
パッケージ化を利用することによって、どのクラスを利用するのか、同じ名前のクラスが存在しても、名前の衝突を避けそれぞれのクラスを利用することができる。

**⑤getter/setterメソッドを用意する**
getter/setterは、作成したプロパティ（メンバ変数）に外部からアクセスするためのメソッドでカプセル化」を実現するために作成する
getterは、JavaBeansのプロパティから値を取得するために利用するメソッド。
以下の規則でメソッドを作成する。
・メソッド名は「getプロパティ名（メンバ変数名）」
・対応するプロパティの値を返却する
setterは、JavaBeansのプロパティに値を格納するために利用するメソッド。
以下の規則でメソッドを作成する。
・メソッド名は「setプロパティ名(メンバ変数名)」
・対応するプロパティに格納する値を受け取り、プロパティに代入する
（使っているツールがeclipseならメンバ変数を作成した状態でgetter/setterメソッドを作りたいクラスを右クリック→「ソース」→「getter及びsetterの生成」で手軽に作成する事が出来る）

以上がJavaBeansの設計ルールになるが必須のルールと必要な時に記述するルールに分かれているので状況に応じて使い分ける。
**＊Beanは上記の設計ルールに則って作られたクラスの総称で使う場面に応じて「Form」、「Entity」、「Dto」と呼び方や使い方が変わる**

こちらの記事で分かりやすく説明されています↓

https://qiita.com/mtanabe/items/c879d233d297eda288d4

またBeanには自分で作りたいオリジナルのgetter/setterメソッドを用意する事も出来る。

```
// ④パッケージ化
package bean;

import java.io.Serializable;

// ①クラスをpublicで宣言
public class RegisterBean implements Serializable{　// ③java.io.Serializableを実装
  private String name;
  private String age;
  private String[] langs;

  // ②引数なしのpublicコンストラクタを作成
  public RegisterBean(){
  }
  
  // ⑤setterメソッドを用意
  public void setName(String name){
    this.name = name;
  }
 
  public void setAge(String age){
    this.age = age;
  }
  public void setLangs(String[] langs){
    this.langs = langs;
  }
  
  // ⑤getterメソッドを用意
  public String getName(){
    return name;
  }
  public String getAge(){
    return age;
  }
  public String[] getLangs(){
    return langs;
  }
  // ここまででBeanとしての条件は満たしている

　　　　// 以下はオリジナルのgetter/setterメソッド
  public String getJpnAge(){
    String jpnAge;
    if(age.equals("child")){
      jpnAge = "18歳未満";
    } else {
      jpnAge = "18歳以上";
    }
    return jpnAge;
  }

  public String getStrLangs(){
    String strLangs = "";
    for(int i = 0; i < langs.length; i++){
      strLangs = strLangs + langs[i] + " ";
    }
    return strLangs;
  }
}
```

### JavaBeans仕様のクラスの使い方
```:氏名や電話番号といったユーザー情報を保持するBean
package beans;

import java.io.Serializable;
public class UserInfoBean implements Serializable {
    private String lastName;
    private String firstName;
    private String address;

    public UserInfoBean() { 
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
```
パッケージ化したUserInfoBeanをimportして利用する
```
//パッケージ名とクラス名を記述
import beans.UserInfoBean;

public class Main {
    public static void main(String[] args) {
        // Beanを生成
        UserInfoBean userInfoBean = new UserInfoBean();

        // getterを使ってプロパティを代入
        userInfoBean.setFirstName("太郎");
        userInfoBean.setLastName("佐藤");
        userInfoBean.setAddress("東京都中央区");

        // setterを使ってプロパティを取得
        System.out.printf("%s %sさんは%sに住んでいます",
                userInfoBean.getLastName(),
                userInfoBean.getFirstName(),
                userInfoBean.getAddress());
    }
}
```
```:出力結果
佐藤 太郎さんは東京都中央区に住んでいます
```
＊「%s」は文字列を出力するフォーマット指定子

## Dao
「Data Access Object」の略でデータベースへのアクセスを行うクラス（Daoクラス）を作り、そのクラスを通してデータベースへアクセスするデザインパターンになりデータベース処理に必要な情報や処理をまとめて管理するオブジェクトの事。
データベースの接続情報を持ち、データベースにアクセスしてデータの取得や操作を行う。

Daoを用いることで
①開発作業を並行しながら行える。
②プログラムの再利用が可能になる。
③メンテナンス（修正）が簡単になる。
**取得した値は「Bean」に格納する。**

### DAOとBeanとDB(データベース)の関係の概念図
![スクリーンショット 2023-01-08 12.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/b2f11f96-d547-a9a8-a7d6-b21bdafa1356.png)
![スクリーンショット 2023-01-08 12.12.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/7d742869-b03e-bee2-6479-38e41e03eb89.png)

## サンプルコード
StudentdtoやStudentBeanのオブジェクトを使ってデータベースから取ってきたデータをDaoからサーブレットに渡したりJSPに渡したりという風に処理を進めていく

```:ブラウザの画面
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>ボタン画面</title>
</head>
<body>
  <h2>生徒全員の情報を表示します</h2>
  <form action="/dbweb/showStudents" method="post">
  <input type="submit" value="実行" />
  </form>
</body>
</html>
```
formタグ内のaction属性で実行ボタンが押された時に呼び出すサーブレットをshowStudentsに指定している

```:Controller(Servlet)
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import bean.StudentDTO;

@WebServlet("/showStudents")
public class ShowStudentsServlet extends HttpServlet {
  public void doPost(HttpServletRequest req, HttpServletResponse res)
      throws IOException, ServletException {
    //DAOオブジェクトを生成
    StudentDAO2 sdao = new StudentDAO2();
    //全件検索した結果をDTOオブジェクト（Bean）として取得
    StudentDTO sdto = sdao.select();
    //検索結果をリクエストスコープに格納
    req.setAttribute("sdto", sdto);
    //JSPにフォワード
    RequestDispatcher rd = req.getRequestDispatcher("/showstudents.jsp");
    rd.forward(req, res);
  }

  public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws IOException, ServletException {
    doPost(req, res);
  }
}
```
```:Model(Dao)
import java.sql.*;
import bean.*;

public class StudentDAO2 {
  private final String URL = "jdbc:mysql://localhost/sampledb";
  private final String USER = "root";
  private final String PASS = "pass";
  private Connection con = null;

  public void connect() {
    try {
      // ①DBに接続
      con = DriverManager.getConnection(URL, USER, PASS);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public StudentDTO select() {
    Statement stmt = null;
    ResultSet rs = null;
    StudentDTO sdto = new StudentDTO();
    String sql = "SELECT * FROM student";
    try {
      connect();
      // ②ステートメントを生成
      stmt = con.createStatement();
      // ③SQLを実行
      rs = stmt.executeQuery(sql);
      // ④検索結果の処理
      while (rs.next()) {
        StudentBean sb = new StudentBean();
        sb.setNo(rs.getInt("no"));
        sb.setName(rs.getString("name"));
        sb.setScore(rs.getInt("score"));
        sdto.add(sb);
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        if (rs != null)
          rs.close();
        if (stmt != null)
          stmt.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    disconnect();
    return sdto;
  }

  public void disconnect() {
    try {
      // ⑤DBを切断
      if (con != null)
        con.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
} 
```
Daoの中では四つの変数が定義されている（5~8行目）。5~7行目でDBに接続するための値をフィールドで定数化し、８行目ではConnectionのオブジェクトを初期値nullで宣言してる。
connect()メソッド内で「DriverManager」クラスで用意されている"getConnection"メソッドを使いデータベースへの接続を確立している。この処理にはtry~catch文内での記述が必須になる。

select()メソッドは戻りの型をBeanであるStudentDaoクラスにしている。
問い合わせ取得結果になるStatementオブジェクトと実行結果のデータになるResuletSetオブジェクトをnullで初期化している。
22行目でStudentDtoのオブジェクトをnewすることでDtoのメモリを生成している。
23行目ここで今回実行するSQL文(studentテーブルの全件検索)を定義している。(実際に全件検索を実行しているのが29行目のexecuteQueryメソッド)
while分の処理が終わったら続いて42~43行目でStatementとResultSetのcloseメソッドを呼び出す。
そして48行目のdisconnectメソッドを呼び出してデータベースと切断し最後に49行目のsdtoのオブジェクトを呼び出し元であるサーブレットにリターンするというプログラムになっている。

```:Bean
package bean;

import java.io.Serializable;

public class StudentBean implements Serializable{
  private int no;
  private String name;
  private int score;
  
  public void setNo(int no){
    this.no = no;
  }
  public void setName(String name){
    this.name = name;
  }
  public void setScore(int score){
    this.score = score;
  }
  public int getNo(){
    return no;
  }
  public String getName(){
    return name;
  }
  public int getScore(){
    return score;
  }
}
```
メンバー変数としてStudentテーブルに合わせてナンバーとネームとスコアの3つの情報を持たせている。
10行目から27行目はこの3つの
メンバー変数に対するセッターとゲッターを定義しているというクラスになっている

```:Bean(Dto)
package bean;

import java.io.Serializable;
import java.util.ArrayList;

public class StudentDTO implements Serializable{
  private ArrayList<StudentBean> list;

  public StudentDTO(){
    list = new ArrayList<StudentBean>();
  }
  public void add(StudentBean sb){
    list.add(sb);
  }
  public StudentBean get(int i){
    return list.get(i);
  }
  public int size(){
    return list.size();
  }
} 
```
Beanとして作っているので1行目でパッケージ化、６行目でSerializableインターフェースを実装している。
７行目でジェネリクスの記述でStudentBeanクラスのオブジェクトが入る変数listを宣言している。
9~10行目で引数無しコンストラクタを作っている（StudentDtoのオブジェクトを生成したタイミングで変数listに対してArrayListのオブジェクトをnewして作っているという記述）

```:View(Jsp)
<%@page contentType="text/html;charset=utf-8" %>
<%@page import="bean.*" %>
<jsp:useBean id ="sdto" scope="request" class="bean.StudentDTO" />
<html>
  <head>
    <title>表示画面</title>
  </head>
<body>
<h2>生徒全員の情報は次の通りです</h2>
<table border="0">
  <tr>
    <th width="50">番号</th>
    <th width="50">名前</th>
    <th width="50">点数</th>
  </tr>
<%
  for(int i = 0; i < sdto.size(); i++){
    StudentBean sb = sdto.get(i);
%>
  <tr>
    <td align="center"><%= sb.getNo() %></td>
    <td align="center"><%= sb.getName() %></td>
    <td align="center"><%= sb.getScore() %></td>
  </tr>
<% } %>
</table>
</body>
</html>
```
2行目でBeanパッケージに含まれているStudentDtoクラスとStudentBeanクラスの情報を読み込んでいる。
3行目ではuseBeabタグを使ってConntrollerでリクエストスコープに格納した変数sdtoを取り出して使うという宣言をしている。

**上記サンプルコードのイメージ図**
![スクリーンショット 2023-01-28 19.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/13d88190-5423-5d55-7a0b-1b747952a4d2.png)
```:studentテーブル
DELETE FROM student;
INSERT INTO student VALUES(1,'菅原',60);
INSERT INTO student VALUES(2,'櫻井',100);
INSERT INTO student VALUES(3,'田原',85);
INSERT INTO student VALUES(4,'中川',90);
INSERT INTO student VALUES(5,'鈴木',75);
INSERT INTO student VALUES(6,'小林',95);
INSERT INTO student VALUES(7,'藤原',90);
INSERT INTO student VALUES(8,'草野',85);
INSERT INTO student VALUES(9,'常田',80);
INSERT INTO student VALUES(10,'大橋',75);
```



## 参考記事
https://www.youtube.com/watch?v=FllARHhidUc&list=PLru8-xuz0YvycnjfIkn8_Sqpe-n2_5xPN&index=12

https://camp.trainocate.co.jp/magazine/whats-javabeans/

https://www.bold.ne.jp/engineer-club/java-beans#-2

https://itsakura.com/java-dto-dao

https://qiita.com/mtanabe/items/c879d233d297eda288d4

https://www.youtube.com/watch?v=Ey2gbUUP-RA&list=PLru8-xuz0YvzEE_qHslDvFaRXxR_Q8m6y&index=11