ITツールの使い方
PhotoShop、Illustrator、Dreamweaver、PowerPoint等の簡潔な使用法説明
コンテンツへスキップ
  • ホーム
  • Adobe ツール
    • Adobe フォトショップ
    • Adobe イラストレータ
    • Adobe アニメート
    • Adobe DreamWeaver
  • Webサイト作成のために
    • HTML詳細
    • CSS詳細
    • WordPress
      • WP 機能
      • サイト、ページの作成
      • サイトの運用・管理
      • BizVektor
    • jQuery
    • ウェブサイト作成の秘訣
      • 色の選択
  • IT基礎知識
    • C
    • Ruby
    • JSP_Servlet
    • eclipse
    • C++
    • Databese
      • PostgreSQL
    • Javascript
      • Javascript 関数
    • Java
    • jQuery
    • Ajax
    • IT用語
  • その他
    • iPhone, iPad
    • MS office
    • PC メンテナンス
  • 投稿一覧
← ログイン処理(Daoを使った改良版)
マークダウン記法を試す →

ログイン処理(DAOを使った汎用的で現実的な構造)

投稿日: 2017年6月22日 作成者: 関口郁夫

前回のデータの永続化機構(データベースやデータファイル)とビジネスロジック間にDAO:Data Access Objectを配し、データの永続化機構をビジネスロジックから隠蔽する方法を説明しました。今回はDAOを使う場合の汎用的で現実的な構造を考えます。
前回のログイン処理(Daoを使った改良版)は、プログラムを簡潔にし保守性、拡張性を高めるためにデータベースアクセスを隠蔽する方法として説明しました。
しかし、実際のデータ永続化機構を使ったアプリケーションの開発では、ビジネスロジックの開発を始めようとするときには利用するデータ永続化機構が決定していない事があります。この場合、何らかのデータ永続化機構を使ったDAOをスタブとして用意しビジネスロジックの開発を進め、データ永続化機構が最終決定した段階でスタブを最終的なDAOに置き換えます。
そのためにはDAOをインターフェースとして用意し、スタブとしてのDAOや最終版のDAOはそれを実装する形にすれば、ビジネスロジックを全く修正することなくこの置き換えが可能です。

インターフェースを利用するログイン処理のクラス関連図は以下のようになります。

インターフェースを利用するログイン処理のクラス関連図

ビジネスロジックはインターフェースであるUserDaoを使って構築し、ビジネスロジックの単体テストまでにスタブとしてのUserDaoImplを作って、UserDaoFactoryのcreateDaoメソッドを使って各機能ごとのDAOを用意します。こうすることによってcreateDaoメソッドとUserDaoを実装するJavaプログラムを書き換えるだけで各種のデータの永続化機構に対応することが出来ます。

まず、ビジネスロジックに対する窓口になるインターフェース:UserDao.javaです。
package com.example;

import java.util.ArrayList;

public interface UserDao  {

	public UserDto findUser(String id);

	public ArrayList<UserDto> getUserList();

	public int regUser(String id, String password);

	public int delUser(String id, String password);
}

ビジネスロジックが必要としているインターフェースだけが記述されています。

次のこのインターフェースをデータベースを使って実装する一つのクラス:UserDaoImpl.javaです。
package com.example;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class UserDaoImpl implements UserDao {

	private static Connection getConnection() {
		try {
			Class.forName("org.postgresql.Driver");
			return DriverManager.getConnection("jdbc:postgresql:login","postgres", "root");
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}
	}

	private static void allClose(PreparedStatement statement, Connection connection) {
		if (statement != null) {
			try {
				statement.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

	}

	static Connection connection = null;
	static PreparedStatement statement = null;

	public UserDto findUser(String id) {
		UserDto user = new UserDto();

		try {
			connection = getConnection();

			statement = connection.prepareStatement("SELECT * FROM userinf WHERE userid = ?");
			statement.setString(1, id);
			ResultSet resultSet = statement.executeQuery();

			if (!resultSet.next()) { return null; }

			user.setUserid(resultSet.getString("userid"));
			user.setPassword(resultSet.getString("password"));

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			allClose(statement, connection);
		}
		return user;

	}
	public ArrayList<UserDto> getUserList() {
		ArrayList<UserDto> list = new ArrayList<UserDto>();

		try {
			connection = getConnection();

			statement = connection.prepareStatement("SELECT * FROM userinf");
			ResultSet resultSet = statement.executeQuery();

			while (resultSet.next()) {
				UserDto ud = new UserDto();
				ud.setNo(resultSet.getInt(1));
				ud.setUserid(resultSet.getString(2));
				ud.setPassword(resultSet.getString(3));
				list.add(ud);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			allClose(statement, connection);
		}
		return list;

	}

	public int regUser(String id, String password) {
		int result = 0;

		try {
			connection = getConnection();

			statement = connection.prepareStatement("INSERT INTO userinf (userid, password) VALUES (?, ?)");
			statement.setString(1, id);
			statement.setString(2, password);
			result = statement.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			allClose(statement, connection);
		}
		return result;

	}

	public int delUser(String id, String password) {
		int result = 0;

		try {
			connection = getConnection();

			statement = connection.prepareStatement("DELETE FROM userinf WHERE userid = ? AND password = ?");
			statement.setString(1, id);
			statement.setString(2, password);
			result = statement.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			allClose(statement, connection);
		}
		return result;

	}

}

この実装は、利用しているデータベースが同じなので前回のログイン処理(Daoを使った改良版)で紹介したDAOと内容が全く同じです。

そして、いろいろな実装の内、利用する実装を指定する:UserDaoFactory.javaです。
package com.example;

public class UserDaoFactory {
	public static UserDaoImpl createDao() {
		return new UserDaoImpl();
	}
}

唯一の機能は実装したUserDaoのインスタンスを返す事です。

一方、ビジネスロジック側ではこれらの構成を使うためにUserDaoFactoryのcreateDao()を使ってUserDaoのインスタンスを取得して、それを使ってデータ永続化機構にアクセスします。
一つの例としてユーザのログイン機能:UserLoginServlet.javaを見てみましょう。
package com.example;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class LoginServlet
 */
@WebServlet("/UserLoginServlet")
public class UserLoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserLoginServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
    @Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");

		String id = request.getParameter("id");
		String password = request.getParameter("password");

		UserDao dao = UserDaoFactory.createDao();
		UserDto user = dao.findUser(id);

		boolean isLogin = (user != null && id.equals(user.getUserid()) && password.equals(user.getPassword()));
		HttpSession session = request.getSession();
		session.setAttribute("isLogin", isLogin);

		if (isLogin) {
			request.setAttribute("username", user.getUserid());
			request.getRequestDispatcher("/user_login_success.jsp").forward(request, response);
		} else {
			request.setAttribute("error", "IDかパスワードが間違っています。\n再入力してください。");
			request.getRequestDispatcher("/user_login.jsp").forward(request, response);
		}

	}
}

37行目でUserDaoFactoryのcreateDao()を呼んでいるのは前回のログイン処理(Daoを使った改良版)のUserLoginServlet.javaの37行目で直接UserDaoをnewしてインスタンスを作っているのと同じです。
他の機能も同じようにUserDaoFactoryのcreateDao()を呼んでUserDaoのインスタンスを取得すればデータ永続化機構を利用することが出来ます。

このような構成をとることにより、以下のようなUserDaoの実装が複数用意される可能性がある場合にも容易に対応することが出来ます。

UserDaoの実装が複数用意されたログイン処理のクラス関連図

以上でDAOを使ったビジネスロジックに対するデータ永続化機構の隠蔽の実現方法についての説明を終わります。
DAOをプログラミングの定石として活用できるように、本ページの説明だけでなくDAOを使わなかった場合、単独のDAOを使ってコードを簡潔に記述する場合の説明も合わせて参考にして頂くと良いでしょう。

カテゴリー: JSP_Servlet タグ: DAO, DaoFactory, implements, interface, login パーマリンク
← ログイン処理(Daoを使った改良版)
マークダウン記法を試す →
  • カテゴリー

    • Adobe DreamWeaver
    • Adobe アニメート
    • Adobe イラストレータ
    • Adobe フォトショップ
    • Ajax
    • BizVektor
    • C
    • C++
    • CSS詳細
    • eclipse
    • HTML詳細
    • iPhone, iPad
    • IT基礎知識
    • IT用語
    • Java
    • Javascript
    • Javascript 関数
    • jQuery
    • JSP_Servlet
    • MS Office
    • PC メンテナンス
    • PostgreSQL
    • Ruby
    • WordPress
    • WP 機能
    • ウェブサイト作成の秘訣
    • サイト、ページの作成
    • サイトの運用・管理
    • 色の選択
ITツールの使い方
Proudly powered by WordPress.