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
1 | package jp.co.f1.jdbc.ch04; |
4 | import java.util.ArrayList; |
6 | public class SampleDAO1 { |
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"; |
15 | // データベース接続用定義を基にデータベースへ接続し、戻り値としてコネクション情報を返す |
16 | private static Connection getConnection(){ |
18 | Class.forName(RDB_DRIVE); |
19 | Connection con = DriverManager.getConnection(URL, USER, PASSWD); |
22 | throw new IllegalStateException(e); |
26 | // データベースからisbnデータの検索を行うメソッド |
27 | // テーブルに登録された全てのisbnデータをArrayListへ格納し、戻り値として返す |
28 | public ArrayList< String > selectIsbnAll(){ |
31 | Connection con = null; // DBコネクション |
32 | Statement smt = null; // SQLステートメント |
35 | ArrayList< String > list = new ArrayList< String >(); |
38 | String sql = "SELECT isbn FROM bookinfo ORDER BY isbn"; |
42 | con = SampleDAO1.getConnection(); |
43 | smt = con.createStatement(); |
46 | ResultSet rs = smt.executeQuery(sql); |
50 | list.add(rs.getString("isbn")); |
53 | }catch(SQLException e){ |
54 | System.out.println("Errorが発生しました!\n"+e); |
58 | try{smt.close();}catch(SQLException ignore){} |
61 | try{con.close();}catch(SQLException ignore){} |
67 | // データベースからtitleデータの検索を行うメソッド |
68 | // テーブルに登録された全てのtitleデータをArrayListへ格納し、戻り値として返す |
69 | public ArrayList< String > selectTitleAll(){ |
71 | Connection con = null; // DBコネクション |
72 | Statement smt = null; // SQLステートメント |
75 | ArrayList< String > list = new ArrayList< String >(); |
78 | String sql = "SELECT title FROM bookinfo ORDER BY isbn"; |
82 | con = SampleDAO1.getConnection(); |
83 | smt = con.createStatement(); |
86 | ResultSet rs = smt.executeQuery(sql); |
90 | list.add(rs.getString("title")); |
93 | }catch(SQLException e){ |
94 | System.out.println("Errorが発生しました!\n"+e); |
98 | try{smt.close();}catch(SQLException ignore){} |
101 | try{con.close();}catch(SQLException ignore){} |
107 | // データベースからpriceデータの検索を行うメソッド |
108 | // テーブルに登録された全てのpriceデータをArrayListへ格納し、戻り値として返す |
109 | public ArrayList< Integer > selectPriceAll(){ |
111 | Connection con = null; // DBコネクション |
112 | Statement smt = null; // SQLステートメント |
115 | ArrayList< Integer > list = new ArrayList< Integer >(); |
118 | String sql = "SELECT price FROM bookinfo ORDER BY isbn"; |
122 | con = SampleDAO1.getConnection(); |
123 | smt = con.createStatement(); |
126 | ResultSet rs = smt.executeQuery(sql); |
130 | list.add(rs.getInt("price")); |
133 | }catch(SQLException e){ |
134 | System.out.println("Errorが発生しました!\n"+e); |
138 | try{smt.close();}catch(SQLException ignore){} |
141 | try{con.close();}catch(SQLException ignore){} |
148 | // 引数に渡された書籍情報をデータベースへ登録し、戻り値として登録件数を返す |
149 | public int insertBook(String isbn, String title, int price){ |
151 | Connection con = null; // DBコネクション |
152 | Statement smt = null; // SQLステートメント |
157 | String sql = "INSERT INTO bookinfo(isbn,title,price) " + |
158 | "VALUES('" + isbn + "','" + title + "'," + price + ")"; |
162 | con = SampleDAO1.getConnection(); |
163 | smt = con.createStatement(); |
166 | rowsCount = smt.executeUpdate(sql); |
168 | }catch(SQLException e){ |
169 | System.out.println("Errorが発生しました!\n"+ e +"\n"); |
173 | try{smt.close();}catch(SQLException ignore){} |
176 | try{con.close();}catch(SQLException ignore){} |
① ソース・フォルダー :myjdbc_kanda/src
② パッケージ :jp.co.f1.jdbc.ch04
③ 名前 :InsertProgram1
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
➢ InsertProgram1.java
1 | package jp.co.f1.jdbc.ch04; |
3 | import java.util.ArrayList; |
5 | public class InsertProgram1 { |
8 | private static ArrayList< String > isbnList = null; // isbn情報格納用のリスト |
9 | private static ArrayList< String > titleList = null; // title情報格納用のリスト |
10 | private static ArrayList< Integer > priceList = null; // price情報格納用のリスト |
12 | public static void main(String[] args) { |
15 | SampleDAO1 objDao = new SampleDAO1(); |
17 | // 書籍情報を取得するメソッドをDAOから呼び出す |
18 | isbnList = objDao.selectIsbnAll(); // isbn情報全て取得メソッド呼び出し |
19 | titleList = objDao.selectTitleAll(); // title情報全て取得メソッド呼び出し |
20 | priceList = objDao.selectPriceAll(); // price情報全て取得メソッド呼び出し |
23 | System.out.println("■登録SQL発行前の書籍一覧表示■"); |
26 | // 書籍情報を登録するメソッドをDAOから呼び出す |
27 | int rowsCount = objDao.insertBook("00008", "Strutsテキスト", 2000); |
29 | System.out.println(rowsCount + "件のレコードを登録しました。\n"); |
32 | // 書籍情報を取得するメソッドをDAOから呼び出す |
33 | isbnList = objDao.selectIsbnAll(); // ISBN情報全て取得メソッド呼び出し |
34 | titleList = objDao.selectTitleAll(); // Title情報全て取得メソッド呼び出し |
35 | priceList = objDao.selectPriceAll(); // Price情報全て取得メソッド呼び出し |
38 | System.out.println("■登録SQL発行後の書籍一覧表示■"); |
42 | System.out.println("エラーが発生しました。" + e); |
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"); |
実行結果
解説
このプログラムは、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パターン