ラベル MySQL の投稿を表示しています。 すべての投稿を表示
ラベル MySQL の投稿を表示しています。 すべての投稿を表示

2014年7月16日水曜日

1-3. PHP+MySQL のサンプル: PDO を使用した簡単なデータ編集の Web アプリ

前項では、すでに非推奨となっている MySQL 関数を使用しましたが、
ここでは PDO を使用します。
さらにデータ検索、追加、変更、削除のできるページを作成します。

member.php

<?php
/**
 * 会員管理コントローラー。
 * 
 * @author 2014/07/13 matsushima
 */
	try {
		require_once "common.php";
		if ("POST" != $_SERVER["REQUEST_METHOD"]) {
			if (isset($_GET["detail"])) {
				// 詳細: 詳細ページ。
				forwardDetail("detail", "detail", null, null);
			} else if (isset($_GET["register"])) {
				// 登録: 編集ページ。
				forwardDetail("register", "edit", null, null);
			} else if (isset($_GET["modify"])) {
				// 変更: 編集ページ。
				forwardDetail("modify", "edit", null, null);
			} else if (isset($_GET["delete"])) {
				// 削除: 詳細ページ。
				forwardDetail("delete", "detail", null, null);
			} else {
				// 一覧: 一覧ページ。
				forwardList();
			}
		} else {
			$model = null;
			$validation = null;
			if (isset($_GET["register"])) {
				if (isset($_POST["confirm"])) {
					if (validate("register", $model, $validation)) {
						// 登録 > 確認: 詳細ページ。
						forwardDetail("register", "detail", $model, $validation);
					} else {
						// 登録 > 確認 > 入力エラー: 編集ページ。
						forwardDetail("register", "edit", $model, $validation);
					}
				} else if (isset($_POST["complete"])) {
					// 登録 > 確認 > 完了: ユーザーを登録 > 一覧ページ。
					validate("register", $model, $validation);
					processRegister($model);
					header("Location: member.php");
				} else if (isset($_POST["correct"])) {
					// 登録 > 確認 > 修正: 編集ページ。
					validate("register", $model, $validation);
					forwardDetail("register", "edit", $model, $validation);
				} else {
					// 登録 > キャンセル: 一覧 or 詳細ページ。
					// 登録 > 確認 > キャンセル: 一覧 or 詳細ページ。
					header("Location: member.php".($_GET["register"] ? "?detail=".$_GET["register"] : ""));
				}
			} else 	if (isset($_GET["modify"])) {
				if (isset($_POST["confirm"])) {
					if (validate("modify", $model, $validation)) {
						// 変更 > 確認: 詳細ページ。
						forwardDetail("modify", "detail", $model, $validation);
					} else {
						// 変更 > 確認 > 入力エラー: 編集ページ。
						forwardDetail("modify", "edit", $model, $validation);
					}
				} else if (isset($_POST["complete"])) {
					// 変更 > 確認 > 完了: ユーザーを変更 > 詳細ページ。
					validate("modify", $model, $validation);
					processModify($model);
					header("Location: member.php?detail=".$_GET["modify"]);
				} else if (isset($_POST["correct"])) {
					// 変更 > 確認 > 修正: 編集ページ。
					validate("modify", $model, $validation);
					forwardDetail("modify", "edit", $model, $validation);
				} else {
					// 変更 > キャンセル: 詳細ページ。
					// 変更 > 確認 > キャンセル: 詳細ページ。
					header("Location: member.php?detail=".$_GET["modify"]);
				}
			} else 	if (isset($_GET["delete"])) {
				if (isset($_POST["complete"])) {
					// 削除 > 完了: ユーザーを削除 > 一覧ページ。
					processDelete($_GET["delete"]);
					header("Location: member.php");
				} else {
					// 削除 > キャンセル: 詳細ページ。
					header("Location: member.php?detail=".$_GET["delete"]);
				}
			}
		}
	} catch (PDOException $e) {
		die("エラーが発生しました: ".$e->getMessage());
	}

/**
 * 入力パラメータ取得・検証。
 */
function validate($func, &$model, &$validation) {
	$model["id"] = $_GET[$func];
	$model["loginid"] = $_POST["loginid"];
	if (!preg_match("/^[a-zA-Z0-9]{1,20}$/", $model["loginid"])) {
		$validation["loginid"] = "20文字以内の英数字で入力してください。";
	}
	$model["password"] = $_POST["password"];
	if (!preg_match("/^[a-zA-Z0-9]{1,20}$/", $model["password"])) {
		$validation["password"] = "20文字以内の英数字で入力してください。";
	}
	$model["password2"] = $_POST["password2"];
	if ($model["password2"] != $model["password"]) {
		$validation["password2"] = "パスワードが異なります。";
	}
	$model["name"] = $_POST["name"];
	if (!preg_match("/^.{1,100}$/", $model["name"])) {
		$validation["name"] = "100文字以内で入力してください。";
	}
	return (count($validation) < 1);
}

/**
 * 一覧ページ。
 */
function forwardList() {
	// ユーザーを検索
	$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = <<<EOD
select
	*
from
	user_mst
where
	loginid like :keyword
	or name like :keyword
EOD;
	if ($_GET["sort"]) {
		$sql .= "\r\norder by\r\n\t".$_GET["sort"].(!isset($_GET["desc"]) ? ' asc' : ' desc');
	}
	$stmt = $dbh->prepare($sql);
	$stmt->execute([":keyword" => "%".$_GET["keyword"]."%"]);
	// 転送
	require_once "member/list.php";
	$dbh = null;
}

/**
 * 詳細ページ。
 */
function forwardDetail($func, $page, $model, $validation) {
	// ユーザーを取得
	if (null == $model) {
		$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
		$sql = <<<EOD
select
	*
from
	user_mst
where
	id = :id
EOD;
		$stmt = $dbh->prepare($sql);
		$stmt->execute([":id" => $_GET[$func]]);
		$model = $stmt->fetch(PDO::FETCH_ASSOC);
		$model["password1"] = $model["password"];
		$model["password2"] = $model["password"];
	}
	// 転送
	require_once "member/".$page.".php";
	$dbh = null;
}

/**
 * ユーザーを登録。
 */
function processRegister($model) {
	// ユーザーを登録
	$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = <<<EOD
insert into
	user_mst
(
	loginid,
	password,
	name
) values (
	:loginid,
	:password,
	:name
)
EOD;
	$stmt = $dbh->prepare($sql);
	$stmt->execute(array_intersect_key($model, ["loginid"=>"","password"=>"","name"=>""]));
	$dbh = null;
}

/**
 * ユーザーを更新。
 */
function processModify($model) {
	// ユーザーを更新
	$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = <<<EOD
update
	user_mst
set
	loginid = :loginid,
	password = :password,
	name = :name
where
	id = :id
EOD;
	$stmt = $dbh->prepare($sql);
	$stmt->execute(array_intersect_key($model, ["id"=>"","loginid"=>"","password"=>"","name"=>""]));
	$dbh = null;
}

/**
 * ユーザーを削除。
 */
function processDelete($id) {
	// ユーザーを削除
	$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
	$sql = <<<EOD
delete from
	user_mst
where
	id = :id
EOD;
	$stmt = $dbh->prepare($sql);
	$stmt->execute(["id" => $id]);
	$dbh = null;
}
?>

member/detail.php

<?php
/**
 * 詳細ページ。
 * 
 * @author 2014/07/14 matsushima
 */
?>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>members</title>
	<link rel="stylesheet" href="/css/default.css" />
</head>
<body id="page">
	<!-- ヘッダ -->
	<div class="header">
		<!-- パンくず -->
		<div class="header-inner">
			<a href="member.php">ユーザー</a>
<?php if (isset($_GET["detail"])) { ?>
			> <a href="member.php?detail=<?=$_GET[$func]?>">詳細</a>
<?php } else if (isset($_GET["register"])) { ?>
			> <a href="member.php?register=<?=$_GET[$func]?>">新規登録</a> > 確認
<?php } else if (isset($_GET["modify"])) { ?>
			> <a href="member.php?modify=<?=$_GET[$func]?>">変更</a> > 確認
<?php } else if (isset($_GET["delete"])) { ?>
			> 削除
<?php } ?>
	
		</div>
	</div>
	<!-- メイン -->
	<div class="main">
		<!-- 詳細 -->
		<table class="detail">
			<tbody>
<?php if (!isset($_GET["register"])) { ?>
				<tr>
					<th>ID</th>
					<td><?=htmlspecialchars($model['id'])?></td>
				</tr>
<?php } ?>
				<tr>
					<th>ログインID</th>
					<td><?=htmlspecialchars($model['loginid'])?></td>
				</tr>
				<tr>
					<th>名前</th>
					<td><?=htmlspecialchars($model['name'])?></td>
				</tr>
			</tbody>
		</table>
<?php if (isset($_GET["detail"])) { ?>
		<form class="form" action="member.php" method="get">
			<button name="modify" value="<?=$model['id']?>">変更</button>
			<button name="delete" value="<?=$model['id']?>">削除</button>
			<button name="register" value="<?=$model['id']?>">コピーして登録</button>
			<button>戻る</button>
		</form>
<?php } else if (isset($_GET["register"]) || isset($_GET["modify"])) { ?>
		登録してよろしいですか?
		<form class="form" action="member.php?<?=$func?>=<?=$_GET[$func]?>" method="post">
			<input type="hidden" name="loginid" value="<?=htmlspecialchars($model['loginid'])?>" />
			<input type="hidden" name="password" value="<?=htmlspecialchars($model['password'])?>" />
			<input type="hidden" name="password2" value="<?=htmlspecialchars($model['password2'])?>" />
			<input type="hidden" name="name" value="<?=htmlspecialchars($model['name'])?>" />
			<input type="submit" name="complete" value="完了" />
			<input type="submit" name="correct" value="修正" />
			<input type="submit" name="cancel" value="キャンセル" />
		</form>
<?php } else if (isset($_GET["delete"])) { ?>
		削除してよろしいですか?
		<form class="form" action="member.php?<?=$func?>=<?=$_GET[$func]?>" method="post">
			<input type="submit" name="complete" value="完了" />
			<input type="submit" name="cancel" value="キャンセル" />
		</form>
<?php } ?>
	</div>
</body>
</html>

member/edit.php

<?php
/**
 * 編集ページ。
 * 
 * @author 2014/07/15 matsushima
 */
?>
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>members</title>
	<link rel="stylesheet" href="/css/default.css" />
</head>
<body id="page">
	<!-- ヘッダ -->
	<div class="header">
		<!-- パンくず -->
		<div class="header-inner">
			<a href="member.php">ユーザー</a>
			>
<?php if (isset($_GET["register"])) { ?>
			<a href="member.php?register=<?=$_GET[$func]?>">新規登録</a>
<?php } if (isset($_GET["modify"])) { ?>
			<a href="member.php?modify=<?=$_GET[$func]?>">変更</a>
<?php } ?>
		</div>
	</div>
	<!-- メイン -->
	<div class="main">
		<!-- 編集 -->
		<form class="form" action="member.php?<?=$func?>=<?=$_GET[$func]?>" method="post">
			<table class="detail">
				<tbody>
<?php if (isset($_GET["modify"])) { ?>
					<tr>
						<th>ID</th>
						<td><?=$model['id']?></td>
					</tr>
<?php } ?>
					<tr>
						<th><label for="loginid">ログインID</label></th>
						<td>
							<input type="text" id="loginid" name="loginid" value="<?=htmlspecialchars($model['loginid'])?>" />
							<label for="loginid" class="error"><?=$validation['loginid']?></label>
						</td>
					</tr>
					<tr>
						<th><label for="password">パスワード</label></th>
						<td>
							<input type="password" id="password" name="password" value="<?=htmlspecialchars($model['password'])?>" />
							<label for="password" class="error"><?=$validation['password']?></label>
						</td>
					</tr>
					<tr>
						<th><label for="password2">(再入力)</label></th>
						<td>
							<input type="password" id="password2" name="password2" value="<?=htmlspecialchars($model['password2'])?>" />
							<label for="password2" class="error"><?=$validation['password2']?></label>
						</td>
					</tr>
					<tr>
						<th><label for="name">名前</label></th>
						<td>
							<input type="text" id="name" name="name" value="<?=htmlspecialchars($model['name'])?>" />
							<label for="name" class="error"><?=$validation['name']?></label>
						</td>
					</tr>
				</tbody>
			</table>
			<input type="submit" name="confirm" value="確認" />
			<input type="submit" name="cancel" value="キャンセル" />
		</form>
	</div>
</body>
</html>

css/default.css

/**
 * デフォルトスタイルシート。
 * 
 * @author 2014/07/14 matsushima
 */

/*
 * デザイン
 */
#page .error {
	color: red;
}

/*
 * ページ
 */
#page {
	margin-top: 0px;
}

/*
 * ヘッダ
 */
#page .header {
	width: 100%;
	background-color: #dddddd;
}
#page .header .header-inner {
	padding: 5px;
}

/*
 * 検索フォーム
 */
#page .form.search {
	margin: 1em 0px;
	padding: 5px;
	background-color: #f1f5ff;
}

/*
 * 一覧
 */
#page .list {
	margin: 1em 0px;
	border-spacing: 0;
	border-collapse: collapse;
}
#page .list th,
#page .list td {
	border: 1px solid black;
	padding: 5px;
}
#page .list thead tr {
	background-color: #dddddd;
}
#page .list tbody tr:nth-child(even) {
	background-color: #f1fff5;
}
#page img.img_sort {
	border: 0px;
	margin-top: 2px;
}

/*
 * 詳細
 */
#page .detail {
	margin: 1em 0px;
}
#page .detail th {
	background-color: #dddddd;
	text-align: right;
	padding: 2px 5px;
}
#page .detail td {
	text-align: left;
	padding: 2px 5px;
}

一覧(検索)ページ


新規登録ページ



コントローラ: ページ遷移など

すべてのページの URL が member.php になっていて、ページの判別をリクエストパラメータで行います。
・一覧・詳細・新規登録・変更・削除は GET の detail, register, modify, delete パラメータ
・新規登録・変更・削除の場合、確認・完了・修正・キャンセルは POST の confirm, complete, correct, cancel パラメータ(ボタンの name 属性)

処理振り分け後、DB 処理を行い、forward または redirect でページ表示を行います。
・forward: require_once member/xxx.php
・redirect: header("Location: member.php?xxx");

ページ一覧
ページURLPOSTデータ転送先
一覧(検索)GET member.php?条件など-forward member/list.php
詳細GET member.php?detail=id-forward member/detail.php
新規登録入力GET member.php?register=(コピー元id)-forward member/edit.php
新規登録確認POST member.php?register=(コピー元id)confirm, 入力データforward member/detail.php
新規登録確認(入力エラー)POST member.php?register=(コピー元id)confirm, 入力データforward member/edit.php
新規登録完了POST member.php?register=(コピー元id)complete, 入力データredirect 一覧
新規登録修正POST member.php?register=(コピー元id)correct, 入力データforward member/edit.php
新規登録キャンセルPOST member.php?register=(コピー元id)cancel, 入力データredirect 一覧 or 詳細
変更、削除略

member.php のページ振り分け処理
if ("POST" != $_SERVER["REQUEST_METHOD"]) {
 if (isset($_GET["detail"])) {
  // 詳細: 詳細ページ。
 } else if (isset($_GET["register"])) {
  // 登録: 編集ページ。
 } else if (isset($_GET["modify"])) {
  // 変更: 編集ページ。
 } else if (isset($_GET["delete"])) {
  // 削除: 詳細ページ。
 } else {
  // 一覧: 一覧ページ。
 }
} else {
 $model = null;
 $validation = null;
 if (isset($_GET["register"])) {
  if (isset($_POST["confirm"])) {
   if (validate("register", $model, $validation)) {
    // 登録 > 確認: 詳細ページ。
   } else {
    // 登録 > 確認 > 入力エラー: 編集ページ。
   }
  } else if (isset($_POST["complete"])) {
   // 登録 > 確認 > 完了: ユーザーを登録 > 一覧ページ。
  } else if (isset($_POST["correct"])) {
    // 登録 > 確認 > 修正: 編集ページ。
  } else {
   // 登録 > キャンセル: 一覧 or 詳細ページ。
   // 登録 > 確認 > キャンセル: 一覧 or 詳細ページ。
  }
 } else  if (isset($_GET["modify"])) {
  if (isset($_POST["confirm"])) {
   if (validate("modify", $model, $validation)) {
    // 変更 > 確認: 詳細ページ。
   } else {
    // 変更 > 確認 > 入力エラー: 編集ページ。
   }
  } else if (isset($_POST["complete"])) {
   // 変更 > 確認 > 完了: ユーザーを変更 > 詳細ページ。
  } else if (isset($_POST["correct"])) {
   // 変更 > 確認 > 修正: 編集ページ。
  } else {
   // 変更 > キャンセル: 詳細ページ。
   // 変更 > 確認 > キャンセル: 詳細ページ。
  }
 } else  if (isset($_GET["delete"])) {
  if (isset($_POST["complete"])) {
   // 削除 > 完了: ユーザーを削除 > 一覧ページ。
  } else {
   // 削除 > キャンセル: 詳細ページ。
  }
 }
}
// GET
// 詳細
// 詳細
// 新規登録
// 新規登録入力
// 変更
// 変更入力
// 削除
// 削除確認
// 一覧
// 一覧

// POST


// 新規登録
// 確認
// 入力 OK
// 新規登録確認
// 入力 NG
// 新規登録入力

// 完了
// 新規登録完了
// 修正
// 新規登録修正
// キャンセル
// 新規登録キャンセル


// 変更
// 確認
// 入力 OK
// 変更確認
// 入力 NG
// 変更入力

// 完了
// 変更完了
// 修正
// 変更修正
// キャンセル
// 変更キャンセル


// 削除
// 完了
// 変更完了
// キャンセル
// 変更キャンセル




モデル: DB 処理など

$dbh = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
DB に接続します。

$stmt = $dbh->prepare($sql);
SQL を実行する準備をします。

$stmt->execute($model);
準備した SQL を実行します。

$model = $stmt->fetch(PDO::FETCH_ASSOC);
select 結果から次の行を取得します。

参考サイト:

http://jp1.php.net/

← 1-2. PHP+MySQL のサンプル
↑ 一覧

2014年7月11日金曜日

1-2. PHP+MySQL のサンプル

データ作成


こちらを参考に、データを作成しておきます。
http://matsu-blo.blogspot.jp/2013/10/1-4mysql.html

サンプル


 sudo gedit /var/www/html/members.php

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>members</title>
</head>
<body>
<?php
	// 接続情報
	$db_server = 'localhost';
	$db_username = 'dbuser';
	$db_password = 'aaa111';
	$db_database_name = 'mydb';
	// サーバーに接続
	if (!mysql_connect($db_server, $db_username, $db_password)) {
		die("!mysql_connect");
	}
	// データベースを選択
	if (!mysql_select_db($db_database_name)) {
		die("!mysql_select_db");
	}
	// クエリを送信
	$result = mysql_query("select * from user_mst");
	if (!result) {
		die("!mysql_query");
	}
	// 結果のフィールド数
	$fields_num = mysql_num_fields($result);
	echo "$fields_num result(s)\n";
?>
<table border="1">
<tr>
<?php
	for ($i = 0; $i < $fields_num; ++ $i) {
		// カラム情報
		$field = mysql_fetch_field($result);
		echo "<th>{$field->name}</th>\n";
	}
?>
</tr>
<?php
	// 行を取得
	while ($row = mysql_fetch_row($result)) {
		echo "<tr>\n";
		foreach ($row as $cell) {
			echo "<td>$cell</td>\n";
		}
		echo "</tr>\n";
	}
	// 結果保持用メモリを解放
	mysql_free_result($result);
?>
</table>
</body>
</html>

 ブラウザで http://localhost/members.php へ移動して、表示されれば OK。



参考サイト:

http://blog.livedoor.jp/vine_user/archives/51932495.html

→ 1-3. PHP+MySQL のサンプル: PDO を使用した簡単なデータ編集の Web アプリ
← 1-1. LAMP サーバー環境構築
↑ 一覧

2013年10月21日月曜日

1-5. Spring MVC 3 + Hibernate 4 + MySQL

pom.xml にライブラリを追加
 今回使用するのは以下のライブラリです。
  spring-orm: O/R マッピングとトランザクション管理
  spring-tx: トランザクション管理
  commons-dbcp: DB のコネクションプールを管理
  hibernate-core: Hibernate のライブラリ
  mysql-connector-java: MySQL の JDBC ドライバ
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>jp.matsushima</groupId>
  <artifactId>spring-test</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-test Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <build>
    <finalName>spring-test</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <encoding>UTF-8</encoding>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>3.2.4.RELEASE</version>
    </dependency>
    <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>3.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>3.2.4.RELEASE</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.2.6.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> </dependency>
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>   </dependencies> </project>
dispatcher-servlet.xml
 mvc:annotation-driven, context:component-scan の指定で、jp.matsushima.spring_test 配下のクラスのアノテーションを有効にします。
 dataSource Bean で DB の接続情報を指定します。
org.apache.commons.dbcp.BasicDataSource はコネクションプールをサポートする DataSource です。
 sessionFactory Bean で SessionFactory を指定します。
org.springframework.orm.hibernate4.LocalSessionFactoryBean は Spring で Hibernate をサポートするセッション管理クラスです。
 transactionManager Bean で TransactionManager を指定します。
org.springframework.orm.hibernate4.HibernateTransactionManager は Spring で Hibernate をサポートするトランザクション管理クラスです。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

  <!-- @Controller の付いたクラスを Controller として登録。 -->
  <mvc:annotation-driven />

  <!-- @Controller, @Repository, @Service, @Component の付いたコンポーネントを検出するパッケージの指定。 -->
  <context:component-scan base-package="jp.matsushima.spring_test" />

  <!-- @Controller から view へのマッピング方法の指定。 -->
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp"/>
  </bean>

  <!-- DB 接続設定。 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root" /> <property name="password" value="root" /> </bean> <!-- セッション管理。 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="jp.matsushima.spring_test.model" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <!-- トランザクション管理。 --> <!-- @Transactional によるトランザクション指定を有効。 --> <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
</beans>
jp.matsushima.spring_test.model.User
 sessionFactory の packagesToScan に指定したパッケージ配下にテーブルに対応した Model クラスを作成します。
@Table にテーブル名、@Column にカラム名を指定します。
まず、private でフィールドを記述し、getter/setter は Source -> Generate Getters and Setters... または Limmy で生成します。
package jp.matsushima.spring_test.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * ユーザーマスタ。
 * 
 * @author 2013/10/15 matsushima
 */
@Entity
@Table(name = "user_mst")
public class User {

	/** ID: id, serial, , not null, IDX:, UQ:, PK:○, FK:,  */
	@Id
	@Column(name = "id")
	@GeneratedValue
	private int id;

	/** ログインID: loginid, varchar(100), , not null, IDX:, UQ:, PK:, FK:,  */
	@Column(name = "loginid")
	private String loginid;

	/** パスワード: password, text, , not null, IDX:, UQ:, PK:, FK:,  */
	@Column(name = "password")
	private String password;

	/** 名前: name, text, , not null, IDX:, UQ:, PK:, FK:,  */
	@Column(name = "name")
	private String name;

	/**
	 * ID: id, serial, , not null, IDX:, UQ:, PK:○, FK:,を取得します。
	 * @return ID: id, serial, , not null, IDX:, UQ:, PK:○, FK:,
	 */
	public int getId() {
	    return id;
	}

	/**
	 * ID: id, serial, , not null, IDX:, UQ:, PK:○, FK:,を設定します。
	 * @param id ID: id, serial, , not null, IDX:, UQ:, PK:○, FK:,
	 */
	public void setId(int id) {
	    this.id = id;
	}

	/**
	 * ログインID: loginid, varchar(100), , not null, IDX:, UQ:, PK:, FK:,を取得します。
	 * @return ログインID: loginid, varchar(100), , not null, IDX:, UQ:, PK:, FK:,
	 */
	public String getLoginid() {
	    return loginid;
	}

	/**
	 * ログインID: loginid, varchar(100), , not null, IDX:, UQ:, PK:, FK:,を設定します。
	 * @param loginid ログインID: loginid, varchar(100), , not null, IDX:, UQ:, PK:, FK:,
	 */
	public void setLoginid(String loginid) {
	    this.loginid = loginid;
	}

	/**
	 * パスワード: password, text, , not null, IDX:, UQ:, PK:, FK:,を取得します。
	 * @return パスワード: password, text, , not null, IDX:, UQ:, PK:, FK:,
	 */
	public String getPassword() {
	    return password;
	}

	/**
	 * パスワード: password, text, , not null, IDX:, UQ:, PK:, FK:,を設定します。
	 * @param password パスワード: password, text, , not null, IDX:, UQ:, PK:, FK:,
	 */
	public void setPassword(String password) {
	    this.password = password;
	}

	/**
	 * 名前: name, text, , not null, IDX:, UQ:, PK:, FK:,を取得します。
	 * @return 名前: name, text, , not null, IDX:, UQ:, PK:, FK:,
	 */
	public String getName() {
	    return name;
	}

	/**
	 * 名前: name, text, , not null, IDX:, UQ:, PK:, FK:,を設定します。
	 * @param name 名前: name, text, , not null, IDX:, UQ:, PK:, FK:,
	 */
	public void setName(String name) {
	    this.name = name;
	}
}
jp.matsushima.spring_test.dao.UserDao
jp.matsushima.spring_test.dao.UserDaoImpl
 クエリを定義、実装します。
sessionFactory は @Autowired によってインジェクションされます。
package jp.matsushima.spring_test.dao;

import jp.matsushima.spring_test.model.User;

/**
 * ユーザーマスタ。
 * 
 * @author 2013/10/15 matsushima
 *
 */
public interface UserDao {

	public User selectForAuth(User param);
}
package jp.matsushima.spring_test.dao;

import jp.matsushima.spring_test.model.User;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * ユーザーマスタ。
 * 
 * @author 2013/10/15 matsushima
 */
@Repository
public class UserDaoImpl implements UserDao {

	@Autowired
	private SessionFactory sessionFactory;

	@Override
	public User selectForAuth(User param) {
		return (User)sessionFactory.getCurrentSession().createCriteria(User.class)
				.add(Restrictions.eq("loginid", param.getLoginid()))
				.add(Restrictions.eq("password", param.getPassword()))
				.uniqueResult();
	}
}
jp.matsushima.spring_test.service.UserService
jp.matsushima.spring_test.service.UserServiceImpl
 ビジネスロジックを定義、実装します。
userDao は @Autowired によってインジェクションされます。
package jp.matsushima.spring_test.service;

import jp.matsushima.spring_test.model.User;

/**
 * ユーザーサービス。
 * 
 * @author 2013/10/15 matsushima
 */
public interface UserService {

	/**
	 * 認証。
	 * 
	 * @param param
	 * @return
	 */
	public User auth(User param);
}
package jp.matsushima.spring_test.service;

import jp.matsushima.spring_test.dao.UserDao;
import jp.matsushima.spring_test.model.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * ユーザーサービス。
 * 
 * @author 2013/10/15 matsushima
 */
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;

	/**
	 * 認証。
	 * 
	 * @param param
	 * @return
	 */
	@Override
	@Transactional
	public User auth(User param) {
		if ((null == param.getLoginid()) || (param.getLoginid().isEmpty())
				|| (null == param.getPassword()) || (param.getPassword().isEmpty())) {
			return null;
		}
		return userDao.selectForAuth(param);
	}
}
jp.matsushima.spring_test.controller.LoginController
 リスエストを処理する Controller を実装します。
userService は @Autowired によってインジェクションされます。
 最初の login() は GET の /login リクエストで呼び出され、login.jsp を表示します。
 次の login() は POST の /login で login パラメータがある(後述の login.jsp でログインボタンを押したとき)リクエストで呼び出されます。
userService.auth(param) で送信された loginid, password で user_mst から検索します。
見つかった場合 index.jsp にフォワードします。そのとき user という名前で検索した User を登録します。
見つからなかった場合 login.jsp にフォワードします。そのとき message という名前でエラーメッセージを登録します。
package jp.matsushima.spring_test.controller;

import jp.matsushima.spring_test.model.User;
import jp.matsushima.spring_test.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.ModelAndView;

/**
 * ログインページ。
 * 
 * @author 2013/10/16 matsushima
 */
@Controller
@RequestMapping("/login")
public class LoginController {

	/** ユーザーサービス。 */
	@Autowired
	private UserService userService;

	/**
	 * ログインページ。
	 * 
	 * @return
	 */
	@RequestMapping(method = RequestMethod.GET)
	public String login() {
		return "login";
	}

	/**
	 * ログイン。
	 * 
	 * @param param
	 * @return
	 */
	@RequestMapping(method = RequestMethod.POST, params = {"login"})
	public ModelAndView login(User param) {
		// 認証。
		User result = userService.auth(param);
		if (null != result) {
			// ログイン -> 認証成功: インデックスページ
			return new ModelAndView("index", "user", result);
		} else {
			// ログイン -> 認証失敗: ログインページ
			return new ModelAndView("login", "message", "ログインIDまたはパスワードが違います。");
		}
	}
}
login.jsp
 ログインページを作成します。
${user.loginid}, ${user.password} で送信されたパラメータが再度表示されます。
${message} は失敗時に登録されたエラーメッセージです。
 ログインボタンを押したとき、POST で login パラメータが送信されます。
これによって、2つ目の login() の
@RequestMapping(method = RequestMethod.POST, params = {"login"})
に一致し、このメソッドが呼ばれます。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 
/**
 * ログインページ。
 * 
 * @author 2013/10/20 matsushima
 */
 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>
	<form action="<%=request.getContextPath() %>/login" method="post">
		<label for="loginid">ログインID</label>
		<input type="text" id="loginid" name="loginid" value="${user.loginid}" />
		<br />
		<label for="password">パスワード</label>
		<input type="password" id="password" name="password" value="${user.password}" />
		<br />
		<div style="color: red;">${message}</div>
		<input type="submit" name="login" value="ログイン" />
	</form>
</body>
</html>
index.jsp
 成功したときに登録された user を表示するように修正します。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>
index page<br />
<% if (null != request.getAttribute("user")) { %> ${user.name} さんこんにちは。 <% } %>
</body> </html>
サーバを起動し、ブラウザから http://localhost:8080/spring-test/login にアクセスします。
DB に登録したログインID、パスワードを入力してログインボタンをクリックし、
xxx さんこんにちは。と表示されれば OK です。

プロジェクトの最新版はこちらで公開しています。
https://github.com/matsushima-terunao/blog_java/

→ 1-5-2. Spring MVC 3 + Hibernate 4 + HSQLDB
← 1-4. MySQL のインストールからデータ作成まで
↑ 一覧