package sample.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import sample.entity.ActorEntity;
import sample.service.MyBatisSampleService;
/**
* MyBatisによるO/Rマッピングを使用するコントローラ.
* <p>MyBatisにより実装されたマッパーを通じてデータベースにアクセスし、結果を画面に表示する。
* ここではサンプル・コードをシンプルなものにするため、
* コントローラはマッパー(設計方針にもよるが基本的にDaoレイヤに該当)を直接参照しているが、
* 一般的にはサービス・クラスを通じて間接的に参照するかたちになる。</p>
* <p>このサンプル・プログラムはローカル・マシン上のポート5432でPostgreSQLが稼働しており、
* <a href="http://www.postgresqltutorial.com/postgresql-sample-database/">PostgreSQL Sample Database</a>
* にしたがってサンプル・データベースdvdrentalが構築されていることを前提としている。
* 接続情報のカスタマイズが必要な場合はapplication.propertiesファイルを変更する。</p>
*/
@Controller
@RequestMapping("/mybatis")
public class MyBatisSampleController {
@Autowired
private MyBatisSampleService sampleService;
@RequestMapping({"/", "/index"})
public String index() {
return "/mybatis/index";
}
/**
* パス変数で指定されたIDを使用してactorテーブルからレコードを取得して画面表示する.
* 単一値を返すことを前提としたマッパーのメソッドは、該当する値が存在しなかったり、
* O/Rマッピングに失敗したりすると{@code null}を返す。
* クライアント・コード側ではこれを前提としたコーディングが必要になる(テンプレート側も同様)。
* @param id ID
* @param model モデル
* @return ビュー名
*/
@RequestMapping("/actor/{id}")
public String actor(@PathVariable int id, Model model) {
final ActorEntity a = sampleService.getActorById(id);
model.addAttribute("found", a != null);
if (a != null) {
model.addAttribute("actor", a);
}
return "/mybatis/actor";
}
/**
* actorテーブルから全レコードを取得して画面表示する.
* @param model モデル
* @return ビュー名
*/
@RequestMapping("/actors")
public String actors(Model model) {
final List<ActorEntity> as = sampleService.getActorsList();
model.addAttribute("actors", as);
return "/mybatis/actors";
}
@RequestMapping("/input")
public String input(Model model) {
final ActorEntity actor = new ActorEntity();
actor.setFirstName("Foo");
actor.setLastName("Bar");
model.addAttribute("actor", actor);
return "/mybatis/input";
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(
// @ModelAttributeによりフォーム情報でコマンド・オブジェクトが初期化される
@ModelAttribute("actor") ActorEntity actor,
// 初期化処理中に発生したエラーはすぐ次のBindingResultに格納される
BindingResult result,
Model model) {
// フィールドに設定されている値をチェック
if (actor.getFirstName() == null || actor.getFirstName().isEmpty()
|| actor.getLastName() == null || actor.getLastName().isEmpty()) {
// ここでは問題があれば例外をスローしているが入力画面に戻り、
// バリデーション・エラーのメッセージを表示する実装のほうが親切
throw new IllegalArgumentException("First name and last name must be not null (and not empty).");
}
// フォームの情報からコマンド・オブジェクトを初期化した際のエラー有無をチェック
if (result.hasErrors()) {
// ここでは問題があれば例外をスローしているが入力画面に戻り、
// バリデーション・エラーのメッセージを表示する実装のほうが親切
throw new IllegalArgumentException();
}
// サービスを通じてデータを登録
sampleService.registerActor(actor);
// 処理が無事終わったら一覧ページにリダイレクト
return "redirect:/mybatis/actors";
}
@RequestMapping(value = "/register-and-cancel", method = RequestMethod.POST)
public String registerAndCancel(
@ModelAttribute("actor") ActorEntity actor,
BindingResult result,
Model model) {
try {
sampleService.registerActorAndCancel(actor);
} catch (Exception ex) {
ex.printStackTrace();
}
return "redirect:/mybatis/actors";
}
}