Java DAO(Data Access Object)と DTO(Data Transfer Object)

前回、PosgreSQLのデータベース接続にJDBCドライバを使ってますが、引き続きJDBCドライバを利用していきます。JDBCJava DataBase Connectivity)と呼ばれるクラス群も使っていく感じですかね。 

DAO(Data Access Object)

データベースの接続、切断、SQLの発行など、データベースへのアクセスを専門に扱うクラスを作ってしまって、データベース関連はすべて任せてしまう考え方みたいです。

  1. データベース処理をDAOクラスに一括できる
  2. テーブル構成の変更による影響を小さくできる

1.データベース処理をDAOクラスに一括できる 

他のクラスでデータベースとのやり取りが必要になったら、DAOクラスを使えば済むようです。

2.テーブル構成の変更による影響を小さくできる 

データベースへアクセスしているのはDAOクラスだけになるので、データベースのテーブル構成が変更になっても、影響を受けるのはDAOクラスだけになるようなイメージですかね。(後述するDTOにも影響は出る気はするのですが....)

DTO(Data Transfer Object)

DAOクラスで取得してきたデータを保持するクラスがDTOクラスのようです。DTOクラスの構成は、 

  • テーブルのカラムに対応したフィールド
  • フィールドのgetterとsetter

のようです。DTOクラスでデータを保持するメリットは、データベースへのアクセスを減らせることにあるようです。

一度、DAOクラスでデータベースから取得したデータを使い回す場合は、2度目からはDAOクラスでデータベースへのアクセスを経由せずに、DTOクラスのインスタンスから直接利用すればよくなります。

データベースへのアクセスは時間がかかるため、できる限りデータベースへのアクセスを減らすことが望ましいようです。

f:id:ts0818:20170710201650p:plain

DAOとDTOを利用してデータベースへアクセス

テーブルのカラム名とデータ型に合わせて、DTOクラスにフィールドとgetterやsetterを作成します。 

f:id:ts0818:20170710202933j:plain

テーブルのカラム名とデータ型の確認。

f:id:ts0818:20170710202930j:plain

⇩  SQLのデータ型とJavaのデータ型の対応は下記を参考にしました

SQL のデータ型と Java のマッピング

package sqltest;

import java.sql.Date;

/**
 * Ordersテーブル用DTOクラス
 * @author ts0818
 *
 */
public class OrdersDTO {
  /**
   * フィールド変数
   */
  private int order_id;
  private Date order_date;
  private String client;
  private int order_count;
  
  /**
   * getter order_id
   * @return int order_id
   */
  public int getOrder_id() {
    return order_id;
  }
  
  /**
   * setter order_id
   * @param int order_id
   */
  public void setOrder_id(int order_id) {
    this.order_id = order_id;
  }
  
  /**
   * getter order_date
   * @return Date order_date
   */
  public Date getOrder_date() {
    return order_date;
  }
  
  /**
   * setter order_date
   * @param Date order_date
   */
  public void setOrder_date(Date order_date) {
    this.order_date = order_date;
  }
  
  /**
   * getter client
   * @return String client
   */
  public String getClient() {
    return client;
  }
  
  /**
   * setter client
   * @param String client
   */
  public void setClient(String client) {
    this.client = client;
  }
  
  /**
   * getter order_count
   * @return int order_count
   */
  public int getOrder_count() {
    return order_count;
  }
  
  /**
   * setter order_count
   * @param int order_count
   */
  public void setOrder_count(int order_count) {
    this.order_count = order_count;
  }
    
}

続いてDAOクラス

package sqltest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * Ordersテーブル用のDAOクラス
 * @author ts0818
 *
 */
public class OrdersDAO {

  public List<OrdersDTO> findAll() {
    // DTOクラスのインスタンス格納用
    List<OrdersDTO> ordersDTO = new ArrayList<>();

    // JDBCドライバ読み込み
    try {
      // PostgreSQLドライバの読み込み
      Class.forName("org.postgresql.Driver");
    } catch(ClassNotFoundException e) {
      e.printStackTrace();
    }

    // データベースへの接続
    try(Connection conn = DriverManager.getConnection(
        "jdbc:postgresql:java_postgre",
        "postgres",
        "ts0818"
    );) {
        // sql文を実行するためのオブジェクト生成
      Statement stmt = conn.createStatement();
    // SELECT文の発行
      String sql = "SELECT * FROM orders";
      // sql文の実行結果を取得(データベースからの値)
      ResultSet rset = stmt.executeQuery(sql);

      // データベースから取得した値がある間、
      while(rset.next()) {
        // OrdersDTOクラスのインスタンスを生成
        OrdersDTO dto = new OrdersDTO();
        // カラムorder_idの値をフィールドorder_idにセット
        dto.setOrder_id(rset.getInt("order_id"));
        // カラムorder_dateの値をフィールドorder_dateにセット
        dto.setOrder_date(rset.getDate("order_date"));
        // カラムclientの値をフィールドclientにセット
        dto.setClient(rset.getString("Client"));
        // カラムorder_countの値をフィールドorder_countにセット
        dto.setOrder_count(rset.getInt("order_count"));
        // インスタンスをListに格納
        ordersDTO.add(dto);
        // while文で次のレコードの処理へ?
      }
    } catch(SQLException e) {
      e.printStackTrace();
    }
    // DTOクラスのインスタンスのListを返す
    return ordersDTO;
  }

}

最後に実行クラス

package sqltest;

import java.util.List;

public class OrdersMain {

  public static void main(String[] args) {
    // DAOクラスのインスタンスの生成
    OrdersDAO dao = new OrdersDAO();

    // findAll()メソッドの戻り値OrdersDTOクラスのインスタンスが格納されたList
    List<ordersDTO> orders = dao.findAll();

    // Listの中のOrdersDTOクラスのインスタンスをループで処理
    for(OrdersDTO order: orders) {
      System.out.println("order_id:" + order.getOrder_id());
      System.out.println("order_date:" + order.getOrder_date());
      System.out.println("client:" + order.getClient());
      System.out.println("order_count:" + order.getOrder_count());
    }

  }

}

とりあえず、java_postgreデータベースからordersテーブルの値は取ってこれたようです。

f:id:ts0818:20170710222703j:plain

これって、テーブルの数だけDAOクラスとDTOクラス作るってことになるのかな?

う~ん、想像を絶する感じですね。