9月26日

Rooによる超高速開発

コントローラを作る

Roo Shell で以下のコマンドを実行。

> web mvc controller --class ~.HelloController --preferredMapping /helo

昨日の動作するプロジェクトのバックアップを以下の場所に置いたので、エラーが出る人がこちらからコピーしてみてください。

\\kgakusei1\share\澤田\SE3Java2014\20140925

FormDataクラスを作成する。

package jp.abc;

public class FormData {
	private String input;

	public String getInput() {
		return input;
	}

	public void setInput(String input) {
		this.input = input;
	}
}

index.jspxを編集する。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:jsp="http://java.sun.com/JSP/Page" 
     xmlns:spring="http://www.springframework.org/tags" 
     xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" 
     xmlns:form="http://www.springframework.org/tags/form"
     version="2.0">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <jsp:output omit-xml-declaration="yes"/>
  <spring:message code="label_helo_index" htmlEscape="false" var="title"/>
  <util:panel id="title" title="${title}">
    <spring:message code="application_name" htmlEscape="false" var="app_name"/>
    <h3>
      <spring:message arguments="${app_name}" code="welcome_titlepane"/>
    </h3>
    <p>${message}</p>
    <form:form modelAttribute="formData" action="form">
        <form:input path="input" />
        <input type="submit" />
    </form:form>
  </util:panel>
</div>

HelloController.java を編集する。

package jp.abc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
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;

@RequestMapping("/helo/**")
@Controller
public class HelloController {

    @RequestMapping(method = RequestMethod.POST, value = "{id}")
    public void post(@PathVariable Long id, ModelMap modelMap,
    		HttpServletRequest request,
    		HttpServletResponse response) {
    }

    @RequestMapping
    public String index(Model model) {
    	model.addAttribute("formData", new FormData());
        return "helo/index";
    }

    @RequestMapping(method = RequestMethod.POST, value = "/form")
    public String post(@ModelAttribute FormData form, Errors result, Model model) {
    	model.addAttribute("message", "You typed: " + form.getInput());
    	return "helo/index";
    }
}

Rooは問題が多いのであきらめましょう!

examプロジェクトに戻ります

JUnitを使ったテスト

以下のサイトを参考に。
http://d.hatena.ne.jp/nakaearth/20131204

src/test/java に新規で jp.abc パッケージを作成。
[新規]-[JUnitテストケース]でテストクラスを作成。

package jp.abc;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class HomeControllerTest {

	@Autowired
	private WebApplicationContext wac;

	private MockMvc mockMvc;

	@Before
	public void setUp() throws Exception {
		mockMvc = webAppContextSetup(wac).build();
	}

	@Test
	public void testHome() {
		fail("まだ実装されていません");
	}

	@Test
	public void testQuery() {
		fail("まだ実装されていません");
	}

}

9月25日

Spring Roo プロジェクトを作成する

  1. 新規でSpring Rooプロジェクトを作成
  2. Roo Shell が表示されたら、web mvc setup を実行
  3. サーバーに作成したプロジェクトを追加
  4. ブラウザからアクセス
  5. Roo Shell で以下のコマンドを入力
    persistence setup –provider HIBERNATE –database HYPERSONIC_PERSISTENT

コントローラを作る

Roo Shell で以下のコマンドを実行。

> web mvc controller --class ~.HelloController --preferredMapping /helo

9月19日

STSでRooプロジェクトを作る

Maven install を実行する

[実行]-[maven]-[install]でエラーが出る人は、サーバーに置いた pom.xml をコピーして試してみること。

MyRooApp-0

Maven install に成功したときは、コンソールに以下のように表示される。

MyRooApp-3

wev mbc setup を実行する

Roo Shell でコマンド「web mvc setup」を実行する。

TomcatにMyRooAppを追加する

「サーバー」タブでTomcatにMyRooAppを追加し、Tomcatを開始する。
http://localhost:8080/MyRooAppにアクセスすると、Rooの画面が表示される。

MyRooApp-4

データベースのセットアップ

Roo Shell で以下のコマンドを実行する。

> persistence setup --provider HIBERNATE --database HYPERSONIC_PERSISTENT 

MyRooApp-5

コマンドプロンプトでmavenを使えるようにする

maven をコピーする。
サーバー上のファイル apache-maven-3.2.3-bin.zip をローカルにコピーする。

mvn-1

se3 の下に java フォルダを作成し、そこにZIPファイルを解凍する。

スタートメニューのコンピュータを右クリックし、プロパティを選択する。
システムの詳細設定をクリックする。
環境変数をクリックする。

JAVA_HOMEとPATHの2つの環境変数を追加する。

mvn-2

スタートメニューからコマンドプロンプトを開き、cd コマンドでMyRooAppのフォルダに移動し、mvn install コマンドを実行する。

mvn-3

BUILD FAILED でエラーになった場合は、-Xオプションを指定してmavenを実行する。

> mvn -X install

エラーになった原因が表示されるので、その原因を解決する。

9月18日

Spring Rooを使ってみる

Spring Rooのインストール

以下のサイトを参考に、Spring Roo をインストールする。
Spring Roo チュートリアルをやってみた 1

Springダッシュボードの右下にある 「IDE EXTENSIONS」 をクリック。
「Spring Roo」をチェックしてインストールを実行。

Roo のインストールが終わったら Eclipse を再起動する。

プロジェクトを作成する

メニューから[ファイル]-[新規]-[プロジェクト]を選択する。
Spring内にある「Spring Roo Project」を選択し、「次へ」をクリック。
以下の内容を入力して「次へ」をクリック。
 プロジェクト名: MyRooApp
 Top level package name: jp.abc
「完了」をクリックしてプロジェクトを作成する。

「Roo shell」が表示されるまでしばらく待機する。

プロジェクトが生成さけれど、pom.xml で「プラグイン実行がライフサイクル構成でカバーされていません」のエラーが出ている。
これを解消するには、Eclipseマーケットプレイスで「m2e-apt」をインストールする。

それでもエラーが消えないので、pom.xml のエラー上にマウスカーソルを移動してクイックフィックスを表示し、「新規m2eコネクタの…」をクリックする。

AspectJ のコネクタが表示されるので、それをインストールする。

Eclipseを再起動し、ビルドが実行されると、エラーが消える。

再起動後にビルドが終わらない等が発生した場合は、Eclipseを再起動してみる。

エラーが消えてビルドが完了していれば、MyRooAppプロジェクトを右クリックし、[実行]-[Maven install]を選択する。
コンソールに「BUILD SUCCESS」が表示されることを確認する。

Roo Shell で「web mvc setup」コマンドを入力しENTERで実行する。

9月12日

エンティティの連携

SpringMVCでは関連付けされたエンティティの永続化も簡単にできる。

Profileクラスの追加

Resultは試験番号と得点だけを保持するので、受験者の名前を保持する Profile クラスを追加して関連付け、受験者の名前も永続化できるようにする。

Profile.java

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "profile")
public class Profile {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String name;

	@OneToOne
	private Result result;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Result getResult() {
		return result;
	}

	public void setResult(Result result) {
		this.result = result;
	}
}

ResultクラスにもProfileへの参照を追加する。

Result.java

package jp.abc;

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

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;

@Entity
@Table(name = "result")
public class Result {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	private long id;

	@Length(min=3, max=10)
	@Column(nullable = false, unique = true)
	private String number;

	@Range(min=0, max=100)
	@Column(nullable = false)
	private int score;

	@OneToOne
	private Profile profile;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	public Profile getProfile() {
		return profile;
	}

	public void setProfile(Profile profile) {
		this.profile = profile;
	}
}

インタフェースProfileDaoを作成する。

ProfileDao.java

package jp.abc;

import java.io.Serializable;
import java.util.List;

public interface ProfileDao<T> extends Serializable {
	public List<T> getAll();
	public T findById(long id);
	public void add(T data);
	public void update(T data);
	public void delete(T data);
	public void delete(long id);
}

ProfileDaoの実装クラスProfileDaoImpleを作成する。

ProfileDaoImple.java

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class ProfileDaoImpl implements ProfileDao<Profile> {
	private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistenceUnit");

	public List<Profile> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<Profile> list = null;
		Query query = manager.createQuery("from Profile");
		list = query.getResultList();
		manager.close();
		return list;
	}

	public Profile findById(long id) {
		EntityManager manager = factory.createEntityManager();
		return (Profile)manager.createQuery("from Profile where id = " + id).getSingleResult();
	}

	public void add(Profile data) {
		EntityManager manager = factory.createEntityManager();
		EntityTransaction tx = manager.getTransaction();
		tx.begin();
		manager.persist(data);
		tx.commit();
		manager.close();
	}

	public void update(Profile data) {
		EntityManager manager = factory.createEntityManager();
		EntityTransaction tx = manager.getTransaction();
		tx.begin();
		manager.merge(data);
		tx.commit();
		manager.close();
	}

	public void delete(Profile data) {
		EntityManager manager = factory.createEntityManager();
		EntityTransaction tx = manager.getTransaction();
		tx.begin();
		Profile p = manager.merge(data);
		manager.remove(p);
		tx.commit();
		manager.close();
	}

	public void delete(long id) {
		delete(findById(id));
	}

}

ビューテンプレートを作成する。

profile.jsp

<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${title}</title>
</head>
<body>

<h1>${title}</h1>
<p>${message}</p>

<table>
  <form:form modelAttribute="profile">
    <tr>
      <td></td>
      <td><form:errors path="*" /></td>
    </tr>
    <tr>
      <td><form:label path="name">名前</form:label></td>
      <td><form:input path="name" size="20" /></td>
    </tr>
    <tr>
      <td><form:label path="result">受験番号</form:label></td>
      <td><form:input path="result" size="20" /></td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit"></td>
    </tr>
  </form:form>
</table>

<hr>
<c:if test="${list != null}">
<table>
  <tr><th>ID</th><th>受験番号</th><th>名前</th></tr>
  <c:forEach var="obj" items="${list}">
    <tr>
      <td>${obj.id}</td>
      <td>${obj.result.number}</td>
      <td>${obj.name}</td>
    </tr>
  </c:forEach>
</table>
</c:if>

</body>
</html>

コントローラを作成する。

ProfileController.java

package jp.abc;

import java.util.List;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ProfileController {

	@RequestMapping(value = "/profile", method = RequestMethod.GET)
	public String profile(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "Profileのサンプルです");
		Profile p = new Profile();
		model.addAttribute("profile", p);
		ProfileDao<Profile> dao = new ProfileDaoImpl();
		List<Profile> list = dao.getAll();
		model.addAttribute("list", list);
		return "profile";
	}

	@RequestMapping(value = "/profile", method = RequestMethod.POST)
	public String profileForm(@Valid @ModelAttribute Profile p, Errors result, Model model) {
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample ERROR");
			model.addAttribute("message", "値をチェックしてください");
		} else {
			model.addAttribute("title", "Sample");
			model.addAttribute("message", "Profileのサンプルです");
			ProfileDaoImpl dao = new ProfileDaoImpl();
			dao.add(p);
			List<Profile> list = dao.getAll();
			model.addAttribute("list", list);
		}
		return "/profile";
	}
}

プロパティエディタを作成する。

ResultPropertyEditor.java

package jp.abc;

import java.beans.PropertyEditorSupport;

public class ResultPropertyEditor extends PropertyEditorSupport {
	public String getAsText() {
		Result r = (Result)getValue();
		if (r == null) {
			return "";
		} else {
			return r.getNumber();
		}
	}

	public void setAsText(String value) {
		ResultDao dao = new ResultDaoImpl();
		Result r = dao.find(value);
		setValue(r);
	}
}

コントローラにInitBinderを追加する。

ProfileController.java

	@InitBinder
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		binder.registerCustomEditor(Result.class, new ResultPropertyEditor());
	}

exam-6

受験番号と名前に続いて得点も表示するようにビューテンプレートを変更する。

profile.jsp

<table>
  <tr><th>ID</th><th>受験番号</th><th>名前</th><th>得点</th></tr>
  <c:forEach var="obj" items="${list}">
    <tr>
      <td>${obj.id}</td>
      <td>${obj.result.number}</td>
      <td>${obj.name}</td>
      <td>${obj.result.score}</td>
    </tr>
  </c:forEach>
</table>

exam-7

9月11日

サービスとリポジトリ

DIでサービスを使えるようにするとさらに簡単になる。

application-config.xml

	<bean
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
		id="entityManagerFactory">
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="showSql" value="true" />
			</bean>
		</property>
		<property name="persistenceUnitName" value="persistenceUnit" />
		<property name="dataSource" ref="dataSource" />
		<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
	</bean>
	<bean
		class="org.springframework.orm.jpa.JpaTransactionManager"
		id="transactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	<tx:annotation-driven/>
	<bean
		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
	<jpa:repositories base-package="jp.abc.exam.repositories" />

Serviceを作る

テキストではMyDataServiceになっているが、これはMyDataを扱っているアプリだから。
成績検索アプリではResultを扱うのでResultServiceを作成する。

ResultService.java

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ResultService {
	@PersistenceContext
	private EntityManager manager;

	@Transactional
	public List<Result> getAll() {
		return (List<Result>)manager.createQuery("from Result").getResultList();
	}
}

コントローラでサービスを使う。
テキストでは既存のコントローラを書き換えているが、ここでは新しいコントローラを作成する。

ListController.java

package jp.abc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

@Controller
public class ListController {
	@Autowired
	private ResultService service;
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "Selectのサンプルです");
		List<Result> list = service.getAll();
		model.addAttribute("list", list);
		return "list";
	}
}

JSPを用意する。

list.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${title}</title>
</head>
<body>

<h1>${title}</h1>
<p>${message}</p>

<table>
  <tr><th>ID</th><th>受験番号</th><th>得点</th></tr>
  <c:forEach var="r" items="${list}">
    <tr>
      <td>${r.id}</td>
      <td>${r.number}</td>
      <td>${r.score}</td>
    </tr>
  </c:forEach>
</table>

</body>
</html>

9月5日

成績検索アプリを完成させる

  1. SpringMVCプロジェクトを作成
  2. 成績を検索する画面を作成
  3. HomeControllerを作成
  4. 成績の検索結果を表示する画面を作成
  5. HomeControllerに検索を実行するメソッドを追加
  6. 成績を登録する画面を作成
  7. EditControllerを作成
  8. 成績を登録するリクエストを受け取れるようにする
  9. Resultエンティティを作成
  10. Resultを使うようにedit.jspを修正
  11. DAOを使用してデータベースに保存する
  12. 重複した受験番号を登録できないようにする

検索でエラーを表示する

JSTL の c:if タグを使用して、error != null のときはエラーメッセージを表示し、そうでないときは検索結果を表示する。

result.jsp

<!DOCTYPE html>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${title}</title>
</head>
<body>

<h1>${title}</h1>

<c:if test="${error != null}">
<p style="color:#ff0000;"><b>${error}</b></p>
</c:if>
<c:if test="${error == null}">
<p>
受験番号 ${number} の得点は ${score} です。
</p>
</c:if>

<a href="/exam/home">戻る</a>
</body>
</html>

コントローラでは、結果が見つからないときはエラーメッセージを設定する。

HomeController.java

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String query(@RequestParam("number") String number, Model model) {
		model.addAttribute("title", "成績の検索結果");
		model.addAttribute("number", number);
		ResultDao dao = new ResultDaoImpl();
		Result r = dao.find(number);
		if (r == null) {
			model.addAttribute("error", "存在しない受験番号です");
			model.addAttribute("score", "");
		} else {
			model.addAttribute("score", r.getScore());
		}
		return "result";
	}

重複した受験番号のチェック

Resultエンティティの number の @Column アノテーションで unique = true を指定すると、一意性を保証することになっているが、バリデーションではチェックされないのであまり意味がない。

重複チェックをするには、保存する前に同一の値が存在するかどうかを確認するのがよい。

参考: http://kenro.biz/blog/?p=172

EditController.java

	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	public String add(@Valid @ModelAttribute Result result,
			BindingResult errors, Model model) {
		ResultDao dao = new ResultDaoImpl();
		if (errors.hasErrors()) {
			model.addAttribute("title", "成績の入力");
		} else {
			model.addAttribute("title", "成績の入力");
			model.addAttribute("result", result);
			try {
				dao.add(result);
			} catch (PersistenceException e) {
				model.addAttribute("message", "受験番号が重複しています");
			}
		}
		List<Result> list = dao.getAll();
		model.addAttribute("list", list);
		return "edit";
	}

ResultDaoImpl.java

    public void add(Result result) {
    	EntityManager manager = factory.createEntityManager();
    	EntityTransaction transaction = manager.getTransaction();
    	transaction.begin();
    	Result r = find(result.getNumber());
    	if (r == null) {
    		try {
    			manager.persist(result);
    			transaction.commit();
    		} catch (PersistenceException e) {
    			transaction.rollback();
    		}
        	manager.close();
    	} else {
    		throw new PersistenceException();
    	}
    }

9月4日

試験成績検索アプリを作成する

前期で学習した、SpringMVCを使ってCRUD機能を実装するWebアプリの復習のため、簡単なWebアプリを作成する。

先週の内容の復習

  1. SpringMVCプロジェクトを作成
  2. 成績を検索する画面を作成
  3. HomeControllerを作成
  4. 成績の検索結果を表示する画面を作成
  5. HomeControllerに検索を実行するメソッドを追加
  6. 成績を登録する画面を作成
  7. EditControllerを作成
  8. 成績を登録するリクエストを受け取れるようにする
  9. Resultエンティティを作成
  10. Resultを使うようにedit.jspを修正
  11. DAOを使用してデータベースに保存する

HSQLDBと接続する

Eclipseでプラグインの設定を変更する。
データベース名を変更してHSQLDBサーバーを再起動する。

exam-5

検索の実装

受験番号を元に成績を検索する実装を追加する。

DAOに検索のためのメソッドを追加する。

ResultDao.java

package jp.abc;

import java.io.Serializable;
import java.util.List;

public interface ResultDao extends Serializable {
    public List<Result> getAll();
    public void add(Result result);
    public Result find(String number);
}

ResultDaoImplに検索の実装を追加する。

ResultDaoImpl.java

	public Result find(String number) {
        EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Result> query = builder.createQuery(Result.class);
		Root<Result> root = query.from(Result.class);
		query.select(root).where(builder.equal(root.get("number"), number));
        return manager.createQuery(query).getSingleResult();
	}

HomeController でDAOを利用する。

HomeController.java

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String query(@RequestParam("number") String number, Model model) {
		model.addAttribute("title", "成績の検索結果");
		model.addAttribute("number", number);
		ResultDao dao = new ResultDaoImpl();
		Result r = dao.find(number);
		model.addAttribute("score", r.getScore());
		return "result";
	}

存在しない受験番号だったらエラー表示する。

DAOは、クエリで見つからないときはnullを返すようにする。

ResultDaoImple.java

	public Result find(String number) {
        EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Result> query = builder.createQuery(Result.class);
		Root<Result> root = query.from(Result.class);
		query.select(root).where(builder.equal(root.get("number"), number));
		Result r = null;
		try {
			r = manager.createQuery(query).getSingleResult();
		} catch (NoResultException e) {
			//
		}
		return r;
	}

HomeControllerは結果がnullならメッセージを送信する。

HomeController.java

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String query(@RequestParam("number") String number, Model model) {
		model.addAttribute("title", "成績の検索結果");
		model.addAttribute("number", number);
		ResultDao dao = new ResultDaoImpl();
		Result r = dao.find(number);
		if (r == null) {
			model.addAttribute("message", "存在しない受験番号です");
			model.addAttribute("score", "");
		} else {
			model.addAttribute("score", r.getScore());
		}
		return "result";
	}