DAOパターン

4.1 DAOパターン

 JDBCを利用したアプリケーションを作成する場合、DAOパターン・DTOパターンと呼ばれる2つのプログラムの設計パターンがよく利用されます。2つのデザインパターンは本来はセットで利用されるものですが、各々がどのような役割を果たすのか学習するため、本節ではDAOパターンに焦点をあてて解説します。

4.1.1 DAOパターンとは

 DAO(Data Access Object)パターンとはデータベースへのアクセスを行うクラスを作り、そのクラスを通してデータベースへアクセスするデザインパターンです。メインロジックのなかに記述されていたアクセス部分の処理を1つのクラスに集約し、データベースアクセスの窓口の役割を持たせます。

図 4.1.1 DAOパターンとデータベース接続

4.1.2 DAOパターンの基本的な構成とメリット

 DAOパターンを利用したプログラムでは、メインロジックとデータアクセスの処理を明確に分けてデザインされます。そのため、以下のようなメリットがあります。

  • アプリケーション内でメインロジックとデータベースアクセスの処理を明確に分けることで、独立性や拡張性を高め、修正や変更があった場合に、互いのクラスに影響を与えないようにする。
  • データベースアクセスの機能を1つのクラスに集約するため、アクセス箇所を特定しやすい。
  • データベースアクセス処理の重複した記述を防ぎ、ソースコードをシンプルにする。

図 4.1.2: DAOを利用したアプリケーション

DAOパターンを利用したプログラム

 このプログラムは、データベースへアクセスを行う処理をメソッド化し、1つのクラスとしてまとめたDAOパターンを利用したプログラムです。DAOパターンを使用したプログラムの動きを確認しましょう。
 なお、このプログラムではデータベースアクセスを行う「SampleDAO1.java」とプログラムのメイン処理を記述する「InsertProgram1.java」を作成します。

ソースコード

① ソース・フォルダー      :myjdbc_kanda/src
② パッケージ          :jp.co.f1.jdbc.ch04
③ 名前             :SampleDAO1

➢ SampleDAO1.java
1package jp.co.f1.jdbc.ch04;
2 
3import java.sql.*;
4import java.util.ArrayList;
5 
6public class SampleDAO1 {
7 
8    //接続用の情報をフィールドに定数として定義
9    private static final String RDB_DRIVE="org.mariadb.jdbc.Driver";
10    private static final String URL="jdbc:mariadb://localhost/mybookdb";
11    private static final String USER="bms";
12    private static final String PASSWD="bms123";
13  
14    // データベース接続を行うメソッド
15    // データベース接続用定義を基にデータベースへ接続し、戻り値としてコネクション情報を返す
16    private static Connection getConnection(){
17        try{
18            Class.forName(RDB_DRIVE);
19            Connection con = DriverManager.getConnection(URL, USER, PASSWD);
20            return con;
21        }catch(Exception e){
22            throw new IllegalStateException(e);
23        }
24    }
25  
26    // データベースからisbnデータの検索を行うメソッド
27    // テーブルに登録された全てのisbnデータをArrayListへ格納し、戻り値として返す
28    public ArrayList<String> selectIsbnAll(){
29  
30        // 変数宣言
31        Connection con = null;  // DBコネクション
32        Statement smt = null;   // SQLステートメント
33  
34        // 配列宣言
35        ArrayList<String> list = new ArrayList<String>();
36  
37        // SQL文作成
38        String sql = "SELECT isbn FROM bookinfo ORDER BY isbn";
39  
40        try{
41            // DBに接続
42            con = SampleDAO1.getConnection();
43            smt = con.createStatement();
44  
45            // SQL文発行
46            ResultSet rs = smt.executeQuery(sql);
47  
48            // 検索結果をArrayListに格納
49            while(rs.next()){
50                list.add(rs.getString("isbn"));
51            }
52  
53        }catch(SQLException e){
54            System.out.println("Errorが発生しました!\n"+e);
55        }finally{
56            // リソースの開放
57            if(smt != null){
58                try{smt.close();}catch(SQLException ignore){}
59            }
60            if(con != null){
61                try{con.close();}catch(SQLException ignore){}
62            }
63        }
64        return list;
65    }
66  
67    // データベースからtitleデータの検索を行うメソッド
68    // テーブルに登録された全てのtitleデータをArrayListへ格納し、戻り値として返す
69    public ArrayList<String> selectTitleAll(){
70        // 変数宣言
71        Connection con = null;  // DBコネクション
72        Statement smt = null;   // SQLステートメント
73  
74        // 配列宣言
75        ArrayList<String> list = new ArrayList<String>();
76  
77        // SQL文
78        String sql = "SELECT title FROM bookinfo ORDER BY isbn";
79  
80        try{
81            // DBに接続
82            con = SampleDAO1.getConnection();
83            smt = con.createStatement();
84  
85            // SQL文発行
86            ResultSet rs = smt.executeQuery(sql);
87  
88            // 検索結果をArrayListに格納
89            while(rs.next()){
90                list.add(rs.getString("title"));
91            }
92  
93        }catch(SQLException e){
94            System.out.println("Errorが発生しました!\n"+e);
95        }finally{
96            // リソースの開放
97            if(smt != null){
98                try{smt.close();}catch(SQLException ignore){}
99            }
100            if(con != null){
101                try{con.close();}catch(SQLException ignore){}
102            }
103        }
104        return list;
105    }
106   
107    // データベースからpriceデータの検索を行うメソッド
108    // テーブルに登録された全てのpriceデータをArrayListへ格納し、戻り値として返す
109    public ArrayList<Integer> selectPriceAll(){
110        // 変数宣言
111        Connection con = null;  // DBコネクション
112        Statement smt = null;   // SQLステートメント
113   
114        // 配列宣言
115        ArrayList<Integer> list = new ArrayList<Integer>();
116   
117        // SQL文
118        String sql = "SELECT price FROM bookinfo ORDER BY isbn";
119   
120        try{
121            // DBに接続
122            con = SampleDAO1.getConnection();
123            smt = con.createStatement();
124   
125            // SQL文発行
126            ResultSet rs = smt.executeQuery(sql);
127   
128            // 検索結果をArrayListに格納
129            while(rs.next()){
130                list.add(rs.getInt("price"));
131            }
132   
133        }catch(SQLException e){
134            System.out.println("Errorが発生しました!\n"+e);
135        }finally{
136            // リソースの開放
137            if(smt != null){
138                try{smt.close();}catch(SQLException ignore){}
139            }
140            if(con != null){
141                try{con.close();}catch(SQLException ignore){}
142            }
143        }
144        return list;
145    }
146   
147    // 書籍情報を登録するメソッド
148    // 引数に渡された書籍情報をデータベースへ登録し、戻り値として登録件数を返す
149    public int insertBook(String isbn, String title, int price){
150        // 変数宣言
151        Connection con = null;  // DBコネクション
152        Statement smt = null;   // SQLステートメント
153   
154        int rowsCount = 0;
155   
156        // SQL文
157        String sql = "INSERT INTO bookinfo(isbn,title,price) " +
158                "VALUES('" + isbn + "','" + title + "'," + price + ")";
159   
160        try{
161            // DBに接続
162            con = SampleDAO1.getConnection();
163            smt = con.createStatement();
164   
165            // SQL文発行
166            rowsCount = smt.executeUpdate(sql);
167   
168        }catch(SQLException e){
169            System.out.println("Errorが発生しました!\n"+ e +"\n");
170        }finally{
171            // リソースの開放
172            if(smt != null){
173                try{smt.close();}catch(SQLException ignore){}
174            }
175            if(con != null){
176                try{con.close();}catch(SQLException ignore){}
177            }
178        }
179        return rowsCount;
180    }
181   
182  }

① ソース・フォルダー      :myjdbc_kanda/src
② パッケージ          :jp.co.f1.jdbc.ch04
③ 名前             :InsertProgram1
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

➢ InsertProgram1.java
1package jp.co.f1.jdbc.ch04;
2 
3import java.util.ArrayList;
4 
5public class InsertProgram1 {
6 
7    // 配列宣言
8    private static ArrayList<String> isbnList = null; // isbn情報格納用のリスト
9    private static ArrayList<String> titleList = null;    // title情報格納用のリスト
10    private static ArrayList<Integer> priceList = null;   // price情報格納用のリスト
11  
12    public static void main(String[] args) {
13        try{
14            // DAOオブジェクト化
15            SampleDAO1 objDao = new SampleDAO1();
16  
17            // 書籍情報を取得するメソッドをDAOから呼び出す
18            isbnList = objDao.selectIsbnAll();  // isbn情報全て取得メソッド呼び出し
19            titleList = objDao.selectTitleAll();    // title情報全て取得メソッド呼び出し
20            priceList = objDao.selectPriceAll();    // price情報全て取得メソッド呼び出し
21  
22            // 取得した書籍情報を表示
23            System.out.println("■登録SQL発行前の書籍一覧表示■");
24            display();
25  
26            // 書籍情報を登録するメソッドをDAOから呼び出す
27            int rowsCount = objDao.insertBook("00008", "Strutsテキスト", 2000);
28            if(rowsCount > 0){
29                System.out.println(rowsCount + "件のレコードを登録しました。\n");
30            }
31  
32            // 書籍情報を取得するメソッドをDAOから呼び出す
33            isbnList = objDao.selectIsbnAll();  // ISBN情報全て取得メソッド呼び出し
34            titleList = objDao.selectTitleAll();    // Title情報全て取得メソッド呼び出し
35            priceList = objDao.selectPriceAll();    // Price情報全て取得メソッド呼び出し
36  
37            // 取得した書籍情報を表示
38            System.out.println("■登録SQL発行後の書籍一覧表示■");
39            display();
40  
41        }catch(Exception e){
42            System.out.println("エラーが発生しました。" + e);
43        }
44    }
45  
46    public static void display() {
47        for(int i=0;i<isbnList.size();i++){
48            System.out.print("ISBN→"  + isbnList.get(i)  + "\t");
49            System.out.print("Title→" + titleList.get(i) + "\t");
50            System.out.print("Price→" + priceList.get(i) + "\n");
51        }
52        System.out.println();
53    }
54  
55 }

実行結果

解説

 このプログラムは、DAOクラスを用いたデータベースアクセスを行い、書籍情報の表示と登録を行なっています。
 InsertProgram1の15行目ではDAOクラスであるSampleDAO1をオブジェクト化しています。DAOクラス内のメソッドは、インスタンスメソッドとして定義されているためオブジェクト化が必要です。
   15: SampleDAO1 objDao = new SampleDAO1();

 18行目ではSampleDAO1クラスのselectIsbnAll()メソッドを呼び出し、isbn情報を検索しています。その戻り値としてisbn情報が格納されたArrayListオブジェクトを受け取っています。
   18: isbnList = objDao.selectIsbnAll();

図 4.1.3: selectIsbnAll ()メソッドの流れ

 19行目と20行目も同様にSampleDAO1クラスから各々のメソッドを呼び出し、titleとpriceの格納されたArrayListオブジェクトを受け取ります。
   19: titleList = objDao.selectTitleAll();
   20: priceList = objDao.selectPriceAll();

 24行目ではdisplay()メソッドを呼び出して18行目から20行目で取得したデータを画面に表示しています。
   24: display();

 ここまでがデータベースからデータを取得し、表示するまでの流れになります。

 データの登録処理は27行目で行なっています。27行目ではSampleDAO1クラスのinsertBook()メソッドを呼び出し、引数に登録する書籍のisbn、title、price情報を渡します。insertBook()メソッド内では、引数の情報を基にSQL文を作成・実行し、戻り値として登録された行数(int型の値)を返します。
   27: int rowsCount = objDao.insertBook("00008", "Strutsテキスト", 2000);

図 4.1.4: insertBook()メソッドの流れ

 33行目から39行目では、18行目から24行目と同じ処理を行い、登録結果を表示しています。
   33: isbnList = objDao.selectIsbnAll();
   34: titleList = objDao.selectTitleAll();
   35: priceList = objDao.selectPriceAll();
   38: System.out.println("■登録SQL発行後の書籍一覧表示■");
   39: display();

 このプログラムではisbn、title、priceの3つのArrayListを取得する必要があるため、3種類のSELECTメソッドを記述し使用しています。メソッドの戻り値は1つの型しか返すことができないために、このようなプログラムになっていますが、あまり効率的なプログラムとは言えません。

 次の節では、データの受け渡しを効率よく行うために、DTOクラスについて学習します。

ポイント
  • DAOクラスを利用することでメインロジックとデータアクセスロジックを分けることができる。

NEXT>> 4.2 DAO/DTOパターン

f