8月31日

JPAによるデータベースの利用

5章のために、新規プロジェクトを作成する。

プロジェクト名: MyData

いつもの手順でプロジェクトを生成し、http://localhost:8080/MyData/ にアクセスする。
click to enter が表示されればOK。

pom.xmlの変更

pom.xml に以下の内容を追加する。

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.1</version>
		</dependency>

		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.3.2</version>
		</dependency>

		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>jta</artifactId>
			<version>1.1</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>3.2.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring-framework.version}</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-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.3.4.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

pom.xml を保存したらエラーが出るかも。
エラーが出たらダイアログで「OK」してダイアログを閉じる。

プロジェクトを右クリックして、
[maven]-[プロジェクトの更新]
[実行]-[maven install]
を実行する。

134行目の ${spring.version} でエラーが出る場合は、${spring-framework.version} に変更する。

database.propertiesの作成

Javaリソースの下の src/main/resources の下の spring フォルダを右クリックし[新規]-[ファイル]を選択する。
ファイル名に database.properties を指定して、テキスト p.270 のリスト5-4の内容を入力して保存する。

database.properties

database.driverClassName=org.hsqldb.jdbc.JDBCDriver
database.url=jdbc:hsqldb:mem:mydata
database.username=sa
database.password=

persistence.xmlの作成

Javaリソースの下の src/main/resources を右クリックし[新規]-[フォルダ]を選択する。
フォルダ名に META-INF と入力して完了。

作成した META-INF フォルダを右クリックして[新規]-[XMLファイル]を選択する。(XMLファイルがなければ「その他」から探す)
ファイル名に persistence.xml と入力して完了。

テキスト p.272 の内容を入力する。

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	version="2.0"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
		http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
	<persistence-unit name="persistenceUnit"
					  transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<properties>
			<property name="hibernate.dialect"
					  value="org.hibernate.dialect.HSQLDialect" />
			<property name="hibernate.hbm2ddl.auto" value="create"/>
			<property name="javax.persistence.jdbc.driver"
					  value="org.hsqldb.jdbc.JDBCDriver"/>
			<property name="javax.persistence.jdbc.url"
					  value="jdbc:hsqldb:mem:mydata"/>
		</properties>
	</persistence-unit>
</persistence>

application-config.xml の変更

Javaリソースの下の src/main/resources の下の spring フォルダにある application-config.xml を変更する。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
 
    <context:property-placeholder location="classpath:spring/database.properties"/>
 
    <bean class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" id="dataSource">
        <property name="driverClassName" value="$database.driverClassName}" />
        <property name="url" value="${database.url}" />
        <property name="username" value="${database.username}" />
        <property name="password" value="${database.password}" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="1800000" />
        <property name="numTestsPerEvictionRun" value="3" />
        <property name="minEvictableIdleTimeMillis" value="1800000" />
    </bean>
</beans>

mvc-config.xmlの変更

mvc-config.xml

    <context:component-scan base-package="jp.abc"/>

MyDataクラスの作成

MyDataエンティティクラスを作成する。

Javaリソースの下の src/main/java を右クリックして、[新規]-[クラス]を選択する。
パッケージ名: jp.abc
クラス名: MyData

MyData.java

package jp.abc;

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

@Entity
public class MyData {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@Column(length = 50, nullable = false)
	private String name;

	@Column(length = 200, nullable = true)
	private String mail;

	@Column(nullable = true)
	private Integer age;

	@Column(nullable = true)
	private String memo;

	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 String getMail() {
		return mail;
	}

	public void setMail(String mail) {
		this.mail = mail;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getMemo() {
		return memo;
	}

	public void setMemo(String memo) {
		this.memo = memo;
	}
}

Data Access Object の作成

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

MyDataDao.java

package jp.abc;

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

public interface MyDataDao <T> extends Serializable {
	public List<T> getAll();
	public void add(MyData mydata);
}

実装クラスを作成する。
MyDataDaoImpl.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 MyDataImpl implements MyDataDao<MyData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

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

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

}

8月28日

年齢計算アプリを作成する

入力フォームで生年月日をSelectで入力する。

生年月日を入力してください。
「    」年「  」月「  」日
[計算]

計算ボタンを押すと、生年月日と曜日、満年齢を表示する。

生年月日はxxxx年xx月xx日x曜日です。
満xx歳です。

プロジェクト名: Age
テンプレート: Simple Spring Web Maven

form.jsp

<!DOCTYPE html>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ 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 charset="utf-8">
        <title>年齢計算</title>
    </head>
    <body>
        <h1>年齢計算</h1>
        <div style="font-size: 24pt;">${result}</div>
        <h2>${message}</h2>
        <form:form modelAttribute="formModel">
        <form:select path="year" name="year"
            items="${years}" multiple="false" />年
        <form:select path="month" name="month"
            items="${months}" multiple="false" />月
        <form:select path="day" name="day"
            items="${days}" multiple="false" />日
        <br />
        <input type="submit" value="計算" />
        </form:form>
    </body>
</html>

FormModelを作成する。
ここでは生年月日なので、Year・Month・Dayがあればよい。

FormModel.java

package jp.abc;

public class FormModel {
	private String year;
	private String month;
	private String day;
	public String getYear() {
		return year;
	}
	public void setYear(String year) {
		this.year = year;
	}
	public String getMonth() {
		return month;
	}
	public void setMonth(String month) {
		this.month = month;
	}
	public String getDay() {
		return day;
	}
	public void setDay(String day) {
		this.day = day;
	}
}

コントローラでSelectの要素をListにして渡す。

AgeController.java

	@RequestMapping(value = "/form", method = RequestMethod.GET)
	public String helo(Model model) {
	    model.addAttribute("title", "ModelAndView sample");
	    model.addAttribute("message", "年齢を計算します。");
	    FormModel fm = new FormModel();
	    model.addAttribute("formModel", fm);
	    model.addAttribute("years", getYears());
	    model.addAttribute("months", getMonths());
	    model.addAttribute("days", getDays());
	    return "form";
	}

getYears()・getMonths()・getDays() の各メソッドでは、Listを返す。

getYears()の例

	private List<String> getYears() {
		List<String> list = new ArrayList<String>();
		for (int i = 1900; i <= 2015; i++) {
			list.add(String.valueOf(i));
		}
		return list;
	}

コントローラにPOSTメソッドをリクエストされたときの処理を実装する。

AgeController.java

	@RequestMapping(value = "/form", method = RequestMethod.POST)
	public String rating(@ModelAttribute FormModel formModel, Model model) {
	        model.addAttribute("message", "年齢を計算します。");
	        int y = Integer.parseInt(formModel.getYear());
	        int m = Integer.parseInt(formModel.getMonth());
	        int d = Integer.parseInt(formModel.getDay());
	        String s = getBirthday(y, m, d);
	        s += "<br />";
	        s += "満" + getAge(y, m, d) + "歳です。";
	        model.addAttribute("result", s);
	        FormModel fm = new FormModel();
	        model.addAttribute("formModel", fm);
		    model.addAttribute("years", getYears());
		    model.addAttribute("months", getMonths());
		    model.addAttribute("days", getDays());
	    return "form";
	}

getBirthday() と getAge() を追加する。

	private String getBirthday(int y, int m, int d) {
		Calendar c = Calendar.getInstance();
		c.set(y, m - 1, d);
		SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日 E曜日");
		return f.format(c.getTime());
	}

	private int getAge(int y, int m, int d) {
		Calendar c = Calendar.getInstance();
		int ty = c.get(Calendar.YEAR);
		int tm = c.get(Calendar.MONTH) + 1;
		int td = c.get(Calendar.DATE);
		int age = ty - y;
		if (tm > m) return age - 1;
		if (tm == m && td > d) return age - 1;
		return age;
	}

8月24日

復習として新規にWebアプリを作成する

入力フォームを用意(URLは、 http://localhost:8080/Rating/form )

「○○」さんの「○○」度は? [判定]

判定ボタンを押すと、

「○○さんの ○○度は、○○%です。」

と表示する。

プロジェクト名: Rating
テンプレート: Simple Spring Web Maven

プロジェクトを作成したら、以下を実行。

  1. [Maven]-[プロジェクトの更新]
  2. [実行]-[maven install]

文字化け対策

文字化け対策のために、web.xml を編集。
最後の <web-app> タグの手前に以下の内容を追加。
src/main/webapp/WEB-INF/web.xml

	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

パッケージの設定

使用するパッケージ名を mvc-config.xml に設定。
src/main/webapp/WEB-INF/mvc-config.xml

<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="jp.abc"/>


    <mvc:annotation-driven />

	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	        <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
	        <property name="prefix" value="/WEB-INF/view/"/>
	        <property name="suffix" value=".jsp"/>
	</bean>

</beans>

ルートコンテキストの動作確認

サーバータブの Tomcat7 サーバーに Ratingプロジェクトを追加して Tomcat7 サーバーを再起動。
http://localhost:8080/Rating/ にアクセスすれば、click to enter が表示される。

FormModelの作成

javaリソースの src/java/main を右クリックし、クラスを新規作成する。
パッケージ名: jp.abc
クラス名; FormModel

FormModel.java

package jp.abc;

public class FormModel {
	private String name;
	private String title;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
}

ビューテンプレートの作成

form.jsp を以下のように作成する。

<!DOCTYPE html>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ 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 charset="utf-8">
		<title>なんとか度判定</title>
	</head>
	<body>
		<h1>なんとか度判定</h1>
		<div style="font-size: 24pt;">${result}</div>
		<h2>${message}</h2>
		<form:form modelAttribute="formModel">
		<form:input path="name"/>さんの<form:input path="title"/>度
		<br />
		<input type="submit" value="判定" />
		</form:form>
	</body>
</html>

コントローラを作成する

買い物メモのコントローラを作成する。
テキストでは MyAppController を再利用しているが、ここでは新しく RatingController を作成する。
※開発する際に、名前は重要!

Javaリソースの src/java/main の下にある jp.abc パッケージを右クリックして [新規]-[クラス] を選択。

名前: RatingController

まずは、GET メソッドに対応する部分だけ入力する。

RatingController.java

package jp.abc;

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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class RatingController {

	@RequestMapping(value = "/form", method = RequestMethod.GET)
	public String form(Model model) {
        model.addAttribute("message", "名前と判定したいなにかを入力してください。");
        FormModel fm = new FormModel();
        model.addAttribute("formModel", fm);
		return "form";
	}

}

http://localhost:8080/Rating/form にアクセスする。
なんとか度判定の画面が表示されればOK。

次に POST メソッドに対応する部分を実装する。

RatingController.java

	@RequestMapping(value = "/form", method = RequestMethod.POST)
	public String rating(@Valid @ModelAttribute FormModel formModel, BindingResult result, Model model) {
            model.addAttribute("message", "名前と判定したいなにかを入力してください。");
       	    String s = formModel.getName() + " さんの "
       			 + formModel.getTitle() + "度は、";
       	    float r = (Math.abs(s.hashCode()) % 1001) / 10;
       	    s = s + r + "% です。";
       	    model.addAttribute("result", s);
       	    FormModel fm = new FormModel();
            model.addAttribute("formModel", fm);
	    return "form";
	}

入力チェックの追加

バリデーション用ライブラリをロードする

パッケージエクスプローラで、Memoプロジェクトの一番下にあるファイル pom.xml を開く。
エディタの下にある「pom.xml」タブを選択する。
ファイルの最後の の手前に以下の内容を追加する。

pom.xml

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.1.Final</version>
        </dependency>
    </dependencies>
</project>

保存すると、自動的にプロジェクトがビルドされ、ライブラリをダウンロードしてくれる。

JSPの変更

form.jsp にエラーメッセージを表示するためのタグを追加する。

form.jsp

		<h1>なんとか度判定</h1>
		<div style="font-size: 24pt;">${result}</div>
		<h2>${message}</h2>
		<form:form modelAttribute="formModel">
		<form:errors path="*" cssStyle="color:red" element="div" />
		<form:input path="name"/>さんの<form:input path="title"/>度
		<br />
		<input type="submit" value="判定" />
		</form:form>

コントローラの修正

入力チェックのための@Validアノテーションと、結果を通知するための BindingResult引数を追加する。

RatingController.java

	@RequestMapping(value = "/form", method = RequestMethod.POST)
	public String rating(@Valid @ModelAttribute FormModel formModel, BindingResult result, Model model) {
        model.addAttribute("message", "名前と判定したいなにかを入力してください。");
        if (result.hasErrors()) {
            model.addAttribute("title", "Sample [ERROR]");
            model.addAttribute("message", "値を再チェックしてください");
        } else {
        	String s = formModel.getName() + " さんの "
        			 + formModel.getTitle() + "度は、";
        	float r = (Math.abs(s.hashCode()) % 1001) / 10;
        	s = s + r + "% です。";
        	model.addAttribute("result", s);
        	FormModel fm = new FormModel();
            model.addAttribute("formModel", fm);
        }
		return "form";
	}

FormModelの変更

FormModelに入力チェック方法を示すアノテーションを追加する。

FormModel.java

	@NotEmpty
	private String name;
	@NotEmpty
	private String title;

エラーメッセージをカスタマイズする

@NotEmpty などのアノテーションに message 引数を指定する。

FormModel.java

	@NotEmpty(message = "名前は必須です")
	private String name;
	@NotEmpty(message = "判定内容は必須です")
	private String title;