1
2

【Java/SQL】 データベースを使ったログイン処理 DAO/DTOパターン

Posted at

目次

この記事は5分ほどで読めます。
1. この記事のターゲット層
2. 開発環境
3. ログイン処理の例
4. データベース設計手順
5. 実行フェーズ

1. この記事のターゲット層

「Java・sqlに関する基礎知識を持っているが、ログイン処理の書き方が思いつかない方/参考にしたい方」
「DAO・DTOクラスパターンを使って設計したい方」

  • 基本レベルの記事となります。
  • 記事にあるコードを写経すれば、処理が成功するように丁寧に解説しております。
  • わかりやすさを重視するため難解な要素は排除しております。

2. 開発環境

JavaSE-17
Eclipse 4.24.0 M2
MySQL 8.0.29
MySQL Workbench 8.0.30

3. ログイン処理の例

早速各クラスのご紹介をしていきます。

4. LoginProcessクラス

package develop.appProcess;

import java.util.Optional;
import java.util.Scanner;

import develop.dao.UserDAO;
import develop.dto.UserDTO;

/**
 * ログイン/ログアウトに関するクラス
 */
public class LoginProcess {
	private static final String OPTION_LOGIN = "a";
	private static final String OPTION_END = "b";

	// アプリ起動時に表示
	public void appStart() {
		try (Scanner scanner = new Scanner(System.in)) {
			while (true) {
				System.out.println("下記項目を選択してください");
				System.out.println("【a】ログイン 【b】終了");

				switch (scanner.next()) {
				// ログイン選択時
				case OPTION_LOGIN:
					Optional<UserDTO> optLoginUser = getLoginUser(scanner);
					if (optLoginUser.isPresent()) {
						UserDTO loginUser = optLoginUser.get();
						// 成功時
						System.out.println(loginUser.getName() + "さん。正常にログインしました");
						// ここから先は各々の処理に移行

                        return;
					} else {
						// 失敗時
						System.out.println("ユーザIDまたはパスワードが違います");
					}
					break;
				// 終了選択時
				case OPTION_END:
					appEnd();
					return;
				// その他入力時
				default:
					System.out.println("aまたはbを入力してください");
					break;
				}
			}
		} catch (IllegalArgumentException | NullPointerException e) {
			e.printStackTrace();
		}
	}

	// アプリ終了
	public static void appEnd() {
		System.out.println("アプリを終了いたします");
	}

	// ユーザIDとパスワードが正しいか認証
	public Optional<UserDTO> getLoginUser(Scanner scanner) {
		System.out.println("ユーザIDを入力してください");
		String userIdInput = scanner.next();
		System.out.println("パスワードを入力してください");
		String passwordInput = scanner.next();
		return UserDAO.selectUser(userIdInput, passwordInput);
	}
}
  • while文とswitch文を使用。
  • scannerを使ってログインするか否かを判定。
  • ワンポイントアドバイス

UserDAOクラス

package develop.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Optional;

import develop.dbcontent.ConnectionSetting;
import develop.dto.UserDTO;

/*
 * userテーブルとのやり取りを行うクラス
 */
public class UserDAO {
	// idとpasswordが一致するユーザを取得して返す
	public static Optional<UserDTO> selectUser(String userId, String password) {
		String sqlString = "SELECT * FROM user WHERE user_id = ? AND user_password = ?;";

		try (Connection con = ConnectionSetting.getDbConnect();
				PreparedStatement ps = con.prepareStatement(sqlString);) {
			ps.setString(1, userId);
			ps.setString(2, password);
			ResultSet rs = ps.executeQuery();

			if (rs.next()) {
				// 取得できた場合
				return Optional.of(
						(new UserDTO(rs.getString("user_id"), rs.getString("user_name"),
								rs.getString("user_password"))));
			} else {
				// 取得できなかった場合
				return Optional.empty();
			}
		} catch (SQLException | NullPointerException e) {
			e.printStackTrace();
			return Optional.empty();
		}
	}
}
  • userテーブルからscannerで入力されたユーザIDとパスワードにマッチするユーザを取得します。
  • sql構文をString型に格納します。その際?を使うことで、SQLインジェクション対策ができます。(これでセキュリティ対策ができるんだ~と思っていただければ大丈夫です)
  • 「ps.setString(1, userId)」は1つ目の?にuserIdを設定するという意味です。
  • 以下の3つの役割を持ったオブジェクトを覚えましょう。
    • Connectionは特定のデータベースとの接続を示します。
    • PreparedStatementはSQL文を実行するために使われます。
    • ResultSetはSQLの実行結果を格納するオブジェクトです。
  • Optionalはnullを返す可能性があるオブジェクトに使用します。userIdとpasswordが一致するユーザがいない場合があるので使用しましょう。(これにより、nullを禁止あるいはnullが格納されている可能性があるかを考慮したプログラムの記述を強制することができ、安全性が高まります)

usersDTOクラス(userテーブルのデータの入れ物)

package develop.dto;

/*
 * userテーブルのデータの入れ物
 */
public class UserDTO {
	private String userId = null;
	private String userName = null;
	private String password = null;

	public UserDTO() {
	}

	public UserDTO(String id, String name, String password) {
		this.userId = id;
		this.userName = name;
		this.password = password;
	}

	public String getUserId() {
		return userId;
	}

	public String getName() {
		return userName;
	}

	public String getPass() {
		return password;
	}
}
  • 今回の場合DTOクラスはこれだけです。簡単です。

ConnectionSettingクラス

package develop.dbcontent;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/*
 * 接続先データベースの情報を設定
 */
public class ConnectionSetting {
	private static final String DB_URL = "jdbc:mysql://localhost/user_management?useSSL=false&serverTimezone=Japan&useUnicode=true&characterEncoding=utf8"; // データベース名入力(今回はuser_management)
	private static final String DB_USER = "root"; // データベースの接続ユーザ名(rootで基本的には大丈夫だと思われます)
	private static final String DB_PASS = "<パスワード>"; // 自分の環境のパスワード入力してください
	private static final String DRIVER = "com.mysql.cj.jdbc.Driver";// MySQLのドライバ

	static {
		try {
			// jar ファイルからドライバークラスをロード
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	// データベースに接続
	public static Connection getDbConnect() throws SQLException {
		return DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
	}
}
  • DAOクラスからこのクラスを呼び出すように設計することで、DAOクラスを簡潔に記述できます。役割分担の効果もあります。
  • DB_URL,DB_USER,DB_PASS,DRIVERは上記を参考にして記載してください。ここを記述について暗記しなくても大丈夫です。
  • <データベース名>は今回はusers_managementにいたしました。

Mainクラス

package develop;

import develop.appProcess.LoginProcess;

/*
 * メインクラスです
 */
public class Main {
	public static void main(String[] args) {
		try {
			new LoginProcess().appStart();
		} catch (IllegalStateException | NullPointerException e) {
			e.printStackTrace();
		}
	}
}
  • 起動後すぐにLoginProcessクラスのappStart()が呼び出されるような設計しております
  • このクラスには基本的に処理は書きません(mainクラスに処理をどかーんと書いていくと、のちのちひどい目に遭います...)

4. データベース設計手順

-- データベース作成
CREATE DATABASE user_management;

-- 使用するデータベースを選択
USE user_management;

-- userテーブルを作成
CREATE TABLE user (
user_id CHAR(4) NOT NULL,
user_name VARCHAR(20) NOT NULL,
user_password VARCHAR(20) NOT NULL,
PRIMARY KEY(user_id));

-- userテーブルにデータを格納
INSERT INTO user VALUE ('0001','テスト太郎','hoge');

-- userテーブルに正常に格納できているか確認
SELECT * FROM user_management.user;
  • 上記を参考にしてください(筆者はWorkbenchにて作成いたしました)

5. 実行フェーズ

下記項目を選択してください
【a】ログイン 【b】終了
a
ユーザIDを入力してください
0001
パスワードを入力してください
hoge
テスト太郎さん。正常にログインしました
  • コンソール上でこのように実行ができれば成功です!
    • 拡張しやすい設計なので、これを基盤として制作物をつくってみてもよいでしょう。
  • ワンポイントアドバイス
    • もしSQL系のエラーが発生した場合は、ConnectionSettingまたはUserDAOのSQL文を疑いましょう。ケアレスミスにより、存在しないデータベースまたはuserテーブルを参照しようとしているケースが多いです。(usersテーブルになっているなど)
    • 「aまたはb以外を入力した際の動作」「userIdまたはパスワードを間違えたときの動作」も確認しましょう。

この記事がご好評であれば、Javaでのデータベース操作の「SELECT/INSERT/UPDATE/DELETE」の各記述方法についても投稿したいと考えております。
「いいね & フォロー」いただけますと大変励みになります!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2