html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title th:text="${title}">top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="${title}">MyMsg page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form method="post" action="/msg" 
			th:object="${formModel}" id="myform">
	<!-- 	<input type="hidden" name="mydata_id" th:value="*{mydata_id}" id="myform" /> -->
		<tr><td><label for="title">タイトル</label></td>
			<td><input type="text" name="title" 
				th:value="*{title}"  form="myform" /></td></tr>
		<tr><td><label for="message">メッセージ</label></td>
			<td><textarea name="message"  
				th:text="*{message}" form="myform"></textarea></td></tr>
		<tr><td><label for="mydata">MYDATA_ID</label></td>
			<td><input type="text" name="mydata_id" form="myform" /></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
			<form method="post" action="/search">
			
			<!-- <form method="post" th:action="@{'/search/' + @{param.sorting[0]} + @{param.order[0]}}">-->		
			
			<input type="text" name="kw" th:value="${kw}" />
		<input type="submit" value="検索" />
	</form>
	<table>
	<tr><th>ID</th><th>メッセージ</th><th>タイトル</th></tr>
	<tr th:each="obj : ${datalist}">
		<td><a th:text="${obj.mydata_id}" th:href="@{/sorting(id=${obj.mydata_id})}"></a></td>
		<td th:text="${obj.mydata.name}"></td>
		<td th:text="${obj.title}"></td>
	</tr>
	</table>
</body>
</html>





■Controller

package com.tuyano.springboot;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
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;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tuyano.springboot.repositories.MsgDataRepository;

@Controller
public class MsgDataController {
	private static final Logger logger = LoggerFactory.getLogger(MsgDataController.class);
	@Autowired
	MsgDataRepository repository;
	
	@PersistenceContext
	EntityManager entityManager;
	
	MsgDataDaoImpl dao;
	
	/**
	 * ソート付き一覧表示
	 * @param mav
	 * @param sorting
	 * @param order
	 * @param pagable
	 * @return
	 */
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView msg(
			ModelAndView mav,
			@RequestParam("sorting") String sorting,
			@RequestParam("order")   String order,
			Pageable pagable
			) {
        logger.info("Called getWhiskies.");
        logger.info(sorting);
        logger.info(order);
		mav.setViewName("showMsgData");
		mav.addObject("title","Sample");
		mav.addObject("msg","MsgDataのサンプルです。");
		MsgData msgdata = new MsgData();
		mav.addObject("formModel", msgdata);
		List<MsgData> list = dao.getAll(sorting, order);
//		Page<MsgData> list = dao.getAll(sorting, order, pagable);
		mav.addObject("datalist", list);
		return mav;
	}

	/**
	 * フォームからINSERT処理
	 * @param msgdata
	 * @param result
	 * @param mav
	 * @return
	 */
	@RequestMapping(value = "/msg", method = RequestMethod.POST)
	public ModelAndView msgform(
			@Valid @ModelAttribute MsgData msgdata,
			Errors result, 
			ModelAndView mav) {
		if (result.hasErrors()) {
			mav.setViewName("showMsgData");
			mav.addObject("title", "Sample [ERROR]");
			mav.addObject("msg", "値を再チェックしてください!");
			return mav;
		} else {
			repository.saveAndFlush(msgdata);
			return new ModelAndView("redirect:/msg");
		}
	}

	/**
	 *  検索用
	 * @param kw
	 * @param mav
	 * @return
	 */
	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public ModelAndView search(
//			@Valid @ModelAttribute MsgData msgdata,
			@RequestParam("kw") String kw,
			ModelAndView mav) {
        logger.info("reeeeeeeeeergverkmhrthmrtphgkフォ@gジェオpjth");
        logger.info(kw);
			mav.setViewName("showMsgData");
			mav.addObject("kw", kw);
			MsgData msgdata = new MsgData();
			mav.addObject("formModel", msgdata);
			List<MsgData> list = dao.search(kw);
			mav.addObject("datalist", list);
			return mav;
	}
//	@RequestMapping(value = "/sorting", method = RequestMethod.GET)
//	public ModelAndView sorting(
//			@RequestParam("sorting") String sorting,
//			ModelAndView mav) {
//			List<MsgData> list = dao.getAll("title");
//			return new ModelAndView("redirect:/msg");
//	}

	@PostConstruct
	public void init(){
		System.out.println("ok");
		dao = new MsgDataDaoImpl(entityManager);
	}
}






■yml

spring:
  datasource:
    url: jdbc:mysql://localhost/test
    username: Owner
    password: 
    driverClassName: com.mysql.jdbc.Driver
logging:
    file: logs/myapp.log
    level:
        org.springframework.web: INFO
        org:
            hibernate:
                SQL: DEBUG
                type:
                    descriptor:
                        sql:
                            BasicBinder: TRACE



■Entity

package com.tuyano.springboot;

import java.util.List;

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

@Entity
@Table(name="goods")
public class MyData {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column
	@NotNull
	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;
	
	@OneToMany(cascade=CascadeType.ALL)
	@Column(nullable = true)
	private List<MsgData> msgdatas;
	
	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;
	}
	public List<MsgData> getMsgdatas() {
		return msgdatas;
	}

	public void setMsgdatas(List<MsgData> msgdatas) {
		this.msgdatas = msgdatas;
	}
}



-----------------------------------------------------------------------------------------------------------------------

package com.tuyano.springboot;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "msgdata")
public class MsgData {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column
	@NotNull
	private long mydata_id;

	@Column
	private String title;

	@Column(nullable = false)
	private String message;

	@ManyToOne(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
	@JoinColumn(name="mydata_id",referencedColumnName="id", insertable=false, updatable=false)
	private MyData mydata;

	public MsgData() {
		super();
		mydata = new MyData();
	}

	public MyData getMydata() {
		return mydata;
	}
	
	public long getMydata_id() {
		return mydata_id;
	}

	public void setMydata_id(long mydata_id) {
		this.mydata_id = mydata_id;
	}
	
	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public void setMydata(MyData mydata) {
		this.mydata = mydata;
	}
}






■インターフェーす

package com.tuyano.springboot;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

public interface MsgDataDao<T> {
	public List<MsgData> getAll();
	// ソート用(仮にStringに全部変換してやるけど、多分ジェネリクスでできる)
	public List<MsgData> getAll(String sort_param, String order);
//	public Page<MsgData> getAll(String sort_param, String order, Pageable pagable);
	//検索用
	public List<MsgData> search(String kw);
//	
//	public MsgData findById(long id);
//	public List<MsgData> findByName(String name);
}


■Impl実装クラス

package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import com.tuyano.springboot.MsgData;

@SuppressWarnings("rawtypes")
@Repository
public class MsgDataDaoImpl implements MsgDataDao<MsgDataDao> {
	private EntityManager entityManager;

	public MsgDataDaoImpl() {
		super();
	}
	
	public MsgDataDaoImpl(EntityManager manager) {
		entityManager = manager;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MsgData> getAll() {
		return entityManager
				.createQuery("from MsgData")
				.getResultList();
	}
	
	// ソートによる一覧処理
	@SuppressWarnings("unchecked")
	@Override
	public List<MsgData> getAll(String sorting, String order_str) {
//	public Page<MsgData> getAll(String sorting, String order, Pageable pagable) {
		List<MsgData> list = null;
		//BUilderの取得
		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
		//クエリの生成
		CriteriaQuery<MsgData> query = builder.createQuery(MsgData.class);
		//Rootクラスインスタンスの生成
		Root<MsgData> root = query.from(MsgData.class);
		String asc = "asc";
		
		//sorting
		if (order_str != "") {
//			String order = asc.equals(order_str) ? "asc" : order_str;
			if(asc.equals(order_str)) {
				//指定の文字列でsorting by asc
				query.select(root).orderBy(builder.asc(root.get(sorting)));
			}else {
				//by desc
				query.select(root).orderBy(builder.desc(root.get(sorting)));
			}
		}
		
//		list =  (Page<MsgData>) entityManager.createQuery(query).getResultList();
		list =  entityManager.createQuery(query).getResultList();
		return list;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<MsgData> search(String kw) {
		List<MsgData> list = null;
		String qstr = "from MsgData "
				+ "where mydata_id like :fid "
				+ " or title like :fname"
				+ " or message like :fmessage";
		Long fid = 0L;
		try {
			fid = Long.parseLong(kw);
		}catch(NumberFormatException e){
			e.printStackTrace();
		}
		//https://teratail.com/questions/3300
//		if(isNumber(kw)){
			//検索KWがIDの場合 IDはlong その他はStringで検索
//				Query query = entityManager.createQuery(qstr).setParameter("fid", fid)
//				.setParameter("fname", "%" + kw + "%")
//				.setParameter("fmessage", kw + "%");
//		}
//		else{
//			Query query = entityManager.createQuery(qstr).setParameter("fid", fid)
//			.setParameter("fname", "%" + kw + "%")
//			.setParameter("fmessage", kw + "%");
//		}
		
		Query query = entityManager.createQuery(qstr).setParameter("fid", fid)
				.setParameter("fname", "%" + kw + "%")
				.setParameter("fmessage", kw + "%");
		list = query.getResultList();
		return list;
	}
	
//	// KWがlongかStringかをパース前に判定する
//	public boolean isNumber(String num) {
//	    try {
//	    		fid =Long.parseLong(num);
//		        return true;
//	        } catch (NumberFormatException e) {
//		        return false;
//	    }
//	}
	
//	@SuppressWarnings("unchecked")
//	@Override
//	public List<MsgData> getAll(String sort_param) {
//		List<MsgData> list = null;
//		//BUilderの取得
//		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
//		//クエリの生成
//		CriteriaQuery<MsgData> query = builder.createQuery(MsgData.class);
//		//Rootクラスインスタンスの生成
//		Root<MsgData> root = query.from(MsgData.class);
//		//指定の文字列でsorting
//		query.select(root).orderBy(builder.desc(root.get(sort_param)));
//		list = entityManager.createQuery(query).getResultList();
//		return list;
//	}
	
//	@Override
//	public MsgData findById(long mydata_id) {
//		return (MsgData)entityManager
//				.createQuery("from MsgData where id = " 
//				+ mydata_id).getSingleResult();
//	}
//
//	@SuppressWarnings("unchecked")
//	@Override
//	public List<MsgData> findByName(String name) {
//		return (List<MsgData>)entityManager
//				.createQuery("from MsgData where name = " 
//				+ name).getSingleResult();
//	}
}

0604 OneToMany全然… 'msgdata0_.mydata_id' in 'field list'

package com.tuyano.springboot;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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;
import org.springframework.web.servlet.ModelAndView;

import com.tuyano.springboot.repositories.MsgDataRepository;

@Controller
public class MsgDataController {
	
	@Autowired
	MsgDataRepository repository;
	
	@PersistenceContext
	EntityManager entityManager;
	
	MsgDataDaoImpl dao;

	@RequestMapping(value = "/msg", method = RequestMethod.GET)
	public ModelAndView msg(ModelAndView mav) {
		mav.setViewName("showMsgData");
		mav.addObject("title","Sample");
		mav.addObject("msg","MsgDataのサンプルです。");
		MsgData msgdata = new MsgData();
		mav.addObject("formModel", msgdata);
		List<MsgData> list = (List<MsgData>)dao.getAll();
		mav.addObject("datalist", list);
		return mav;
	}

	@RequestMapping(value = "/msg", method = RequestMethod.POST)
	public ModelAndView msgform(
			@Valid @ModelAttribute MsgData msgdata, 
			Errors result, 
			ModelAndView mav) {
		if (result.hasErrors()) {
			mav.setViewName("showMsgData");
			mav.addObject("title", "Sample [ERROR]");
			mav.addObject("msg", "値を再チェックしてください!");
			return mav;
		} else {
			repository.saveAndFlush(msgdata);
			return new ModelAndView("redirect:/msg");
		}
	}

	@PostConstruct
	public void init(){
		System.out.println("ok");
		dao = new MsgDataDaoImpl(entityManager);
	}
}
package com.tuyano.springboot;

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

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "msgdata")
public class MsgData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column
	private String title;

	@Column(nullable = false)
	private String message;
	
	public long getId() {
		return id;
	}

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

	@ManyToOne
	private MyData mydata;

	public MsgData() {
		super();
		mydata = new MyData();
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public MyData getMydata() {
		return mydata;
	}

	public void setMydata(MyData mydata) {
		this.mydata = mydata;
	}
}
package com.tuyano.springboot;

import java.io.Serializable;
import java.util.List;
import com.tuyano.springboot.MyData;

public interface MyDataDao <T> extends Serializable{
	public List<MsgData> getAll();
}
package com.tuyano.springboot;

import java.util.List;

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

@Entity
@Table(name="goods")
public class MyData {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	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;
	
	@OneToMany(cascade=CascadeType.ALL)
	@Column(nullable = true)
	private List<MsgData> msgdatas;
	
	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;
	}
	public List<MsgData> getMsgdatas() {
		return msgdatas;
	}

	public void setMsgdatas(List<MsgData> msgdatas) {
		this.msgdatas = msgdatas;
	}
}
package com.tuyano.springboot;

import java.util.List;

public interface MsgDataDao<T> {
	public List<MsgData> getAll();
	public MsgData findById(long id);
}
package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.stereotype.Repository;

@SuppressWarnings("rawtypes")
@Repository
public class MsgDataDaoImpl implements MsgDataDao<MsgDataDao> {
	private EntityManager entityManager;

	public MsgDataDaoImpl() {
		super();
	}
	
	
	public MsgDataDaoImpl(EntityManager manager) {
		entityManager = manager;
	}
	

	@SuppressWarnings("unchecked")
	@Override
	public List<MsgData> getAll() {
		return entityManager
				.createQuery("from MsgData")
				.getResultList();
	}
	@Override
	public MsgData findById(long id) {
		return (MsgData)entityManager
				.createQuery("from MsgData where id = " 
				+ id).getSingleResult();
	}

}

2018/06/04
package com.tuyano.springboot.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;

import com.tuyano.springboot.MsgData;

@Repository
public interface MsgDataRepository extends JpaRepository {

}
この状態で
@Repositoryが「Repository is not an annotation type」とのエラー
→importするrepositoriesにすごくよく似たやつがいる
import org.springframework.data.repository.Repository; //☓
import org.springframework.stereotype.Repository; //○


======================================================================================
Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister

======================================================================================
→フィールドに対してsetterがない


======================================================================================
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'msgdata0_.mydata_id' in 'field list'
======================================================================================
https://stackoverflow.com/questions/27797806/com-mysql-jdbc-exceptions-jdbc4-mysqlsyntaxerrorexception-unknown-column-day0
MySQL(テーブル上)のリレーションと、ソース上のリレーションが合致してない


→テーブルを以下のようにreferencesつけて作り直した & @JoinColumn(name="id")つけてみた
======================================================================================
→ (should be mapped with insert="false" update="false")
======================================================================================
// StackOverFlowより"stupid error”
2つのテーブル間で、おんなじカラム名(idとか)同士でくっつけようとするとこのエラー吐くらしい まじか
https://stackoverflow.com/questions/15076463/another-repeated-column-in-mapping-for-entity-error
「If you have already mapped a column and have accidentaly set the same values for name and referencedColumnName in @JoinColumn hibernate gives the same stupid error

Error:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'msgdata0_.mydata_id' in 'field list'

あああああああ゛
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.testtest.SomeCustomEntity column: COLUMN_NAME (should be mapped with insert="false" update="false")」


com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'msgdata0_.msgid' in 'field list'
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'msgdata0_.mydata_id' in 'field list'
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'msgdata0_.mydata_id' in 'field list'


もう一回確認するけど

goods CREATE TABLE `goods` (

`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`mail` varchar(20) DEFAULT NULL,
`memo` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 |

msgdata CREATE TABLE `msgdata` (

`id` int(11)NOT NULL AUTO_INCREMENT,
`title` varchar(20) DEFAULT NULL,
`message` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

①レストコン(@RestController) ・パス変数(@PathVariable) ・ObjをJSON出力(return new HogeObj(id, name[id], mails[id])) ②ThymeLeafでの値埋め込み ・ModelAndView型 ・DB ・リレーション ・WHERE/ ③DBアクセス エンティティクラス リポジトリクラス(@Repository) ・一覧表示(Iterable list = repository.findAll();) ・formからの入力値をINSERT(登録)(repository.saveAndFlush(mydata);) ・EDIT(更新) ・DELETE(更新) ④クエリの工夫 ・ソート(Criteria API) →Jsで起動 ・KW検索 ・ページネーション ・表示件数

ほかサイトのもの

Spring Boot 5 プログラミング入門

掲載リスト


リスト2-1
@RestController
class App {

	@RequestMapping("/")
	def home() {
		"Hello!!"
	}
}


リスト2-2
@RestController
class App {

	@RequestMapping("/")
	def home() {
		def header = "<html><body>"
		def footer = "</body></html>"
		def content = "<h1>Hello!</h1><p>this is html content.</p>"
		
		header + content + footer
	}
}


リスト2-3
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Index Page</title>
	<style>
	body {font-size:16pt; color:#999; }
	h1 { font-size:100pt; text-align:right; color:#f6f6f6;
		letter-spacing:-0.1em;margin:-50px 0px -50px 0px; }
	</style>
</head>
<body>
	<h1>Hello!</h1>
	<p>this is sample web page.</p>
</body>
</html>


リスト2-4
@Grab("thymeleaf-spring5")

@Controller
class App {

	@RequestMapping("/")
	@ResponseBody
	def home(ModelAndView mav) {
		mav.setViewName("home")
		mav
	}
}


リスト2-5
html {
	head {
		title('index page')
	}
	body {
		h1('Hello')
		p('this is Groovy template!')
	}
}


リスト2-6
html {
	head {
		title('index page')
	}
	body {
		h1('Hello')
		p('this is Groovy template!')
		div(){
			a(href:'http://google.com'){
				yield 'google link'
			}
		}
	}
}


リスト2-7
<body>
	<h1>Hello!</h1>
	<p th:text="${msg}">this is sample.</p>
</body>


リスト2-8
// @Grab("thymeleaf-spring5") を追記しておく

@RequestMapping("/")
@ResponseBody
def home(ModelAndView mav) {
	mav.setViewName("home")
	mav.addObject("msg","Hello! this is sample page.")
	mav
}


リスト2-9
mav.addObject("msg","こんにちは!")


リスト2-10
mav.addObject("msg","\u3053\u3093\u306b\u3061\u306f\uff01")


リスト2-11
<body>
	<h1>Hello!</h1>
	<p th:text="${msg}">${msg}</p>
	<form method="post" action="/send">
		<input type="text" name="text1" th:value="${value}" />
		<input type="submit" value="Click" />
	</form>
</body>


リスト2-12
@Grab("thymeleaf-spring5")

@Controller
class App {

	@RequestMapping(value="/", method=RequestMethod.GET)
	@ResponseBody
	def home(ModelAndView mav) {
		mav.setViewName("home")
		mav.addObject("msg","please write your name...")
		mav
	}

	@RequestMapping(value="/send", method=RequestMethod.POST)
	@ResponseBody
	def send(@RequestParam("text1")String str, ModelAndView mav) {
		mav.setViewName("home")
		mav.addObject("msg","Hello, " + str + "!!")
		mav.addObject("value",str)
		mav
	}
}


リスト3-1
package com.tuyano.springboot;

/**
 * Hello world!
 *
 */
public class App 
{
	public static void main( String[] args )
	{
		System.out.println( "Hello World!" );
	}
}


リスト3-2
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.tuyano.springboot</groupId>
  <artifactId>MyBootApp</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>MyBootApp</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>


リスト3-3
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">

	<modelVersion>4.0.0</modelVersion>

	<groupId>com.tuyano.springboot</groupId>
	<artifactId>MyBootApp</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>MyBootApp</name>
	<description>sample project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

</project>


リスト3-4
buildscript {
	ext {
		springBootVersion = '2.0.0.RELEASE'
	}
	repositories {
		mavenCentral()
		maven { url "https://repo.spring.io/snapshot" }
		maven { url "https://repo.spring.io/milestone" }
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
	maven { url "https://repo.spring.io/snapshot" }
	maven { url "https://repo.spring.io/milestone" }
}

dependencies {
	compile('org.springframework.boot:spring-boot-starter-web')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}


リスト3-5
package com.tuyano.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyBootAppApplication {

	public static void main(String[] args) {
		SpringApplication.run(MyBootAppApplication.class, args);
	}
}


リスト3-6
package com.tuyano.springboot;

public class HeloController {

}


リスト3-7
package com.tuyano.springboot;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HeloController {

	@RequestMapping("/")
	public String index() {
		return "Hello Spring-Boot World!!";
	}
}


リスト3-8
package com.tuyano.springboot;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HeloController {

	@RequestMapping("/{num}")
	public String index(@PathVariable int num) {
		int res = 0;
		for(int i = 1;i <= num;i++)
			res += i;
		return "total: " + res;
	}
}


リスト3-9
package com.tuyano.springboot;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HeloController {
	String[] names = {"tuyano",
			"hanako","taro",
			"sachiko","ichiro"};
	String[] mails = {"syoda@tuuyano.com",
			"hanako@flower","taro@yamda",
			"sachiko@happy","ichiro@baseball"};

	@RequestMapping("/{id}")
	public DataObject index(@PathVariable int id) {
		return new DataObject(id,names[id],mails[id]);
	}
	
}

class DataObject {
	private int id;
	private String name;
	private String value;
	
	public DataObject(int id, String name, String value) {
		super();
		this.id = id;
		this.name = name;
		this.value = value;
	}

	public int getId() { return id; }

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

	public String getName() { return name; }

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

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
	
}


リスト3-10
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>


リスト3-11
dependencies {
	compile('org.springframework.boot:spring-boot-starter-thymeleaf')
	compile('org.springframework.boot:spring-boot-starter-web')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}


リスト3-12
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HeloController {
	
	@RequestMapping("/")
	public String index() {
		return "index";
	}
	
}


リスト3-13
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	</style>
</head>
<body>
	<h1>Helo page</h1>
	<p class="msg">this is Thymeleaf sample page.</p>
</body>
</html>


リスト3-14
<body>
	<h1>Helo page</h1>
	<p class="msg" th:text="${msg}"></p>
</body>


リスト3-15
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HeloController {
	
	@RequestMapping("/{num}")
	public String index(@PathVariable int num, Model model) {
		int res = 0;
		for(int i = 1;i <= num;i++)
			res += i;
		model.addAttribute("msg", "total: " + res);
		return "index";
	}
	
}


リスト3-16
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HeloController {
	
	@RequestMapping("/{num}")
	public ModelAndView index(@PathVariable int num, 
			ModelAndView mav) {
		int res = 0;
		for(int i = 1;i <= num;i++)
			res += i;
		mav.addObject("msg", "total: " + res);
		mav.setViewName("index");
		return mav;
	}
	
}


リスト3-17
<body>
	<h1>Helo page</h1>
	<p th:text="${msg}">please wait...</p>
	<form method="post" action="/">
		<input type="text" name="text1" th:value="${value}" />
		<input type="submit" value="Click" />
	</form>
</body>


リスト3-18
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HeloController {
	
	@RequestMapping(value="/", method=RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","お名前を書いて送信してください。");
		return mav;
	}
	
	@RequestMapping(value="/", method=RequestMethod.POST)
	public ModelAndView send(@RequestParam("text1")String str, 
			ModelAndView mav) {
		mav.addObject("msg","こんにちは、" + str + "さん!");
		mav.addObject("value",str);
		mav.setViewName("index");
		return mav;
	}
}


リスト3-19
<!-- pre { font-size:13pt; color:gray; padding:5px 10px; 
		border:1px solid gray; } を<style>に追加 -->
<body>
	<h1>Helo page</h1>
	<pre th:text="${msg}">please wait...</pre>
	<form method="post" action="/">
		<div>
		<input type="checkbox" id="check1" name="check1" />
		<label for="check1">チェック</label>
		</div>
		<div>
		<input type="radio" id="radioA" name="radio1" value="male" />
		<label for="radioA">男性</label>
		</div>
		<div>
		<input type="radio" id="radioB" name="radio1" value="female" />
		<label for="radioB">女性</label>
		</div>
		<div>
		<select id="select1" name="select1" size="4">
			<option value="Windows">Windows</option>
			<option value="Mac">Mac</option>
			<option value="Linux">Linux</option>
		</select>
		<select id="select2" name="select2" size="4" multiple="multiple">
			<option value="Android">Android</option>
			<option value="iphone">iPhone</option>
			<option value="Winfone">Windows Phone</option>
		</select>
		</div>
		<input type="submit" value="Click" />
	</form>
</body>


リスト3-20
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HeloController {
	
	@RequestMapping(value="/", method=RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","フォームを送信下さい。");
		return mav;
	}
	
	@RequestMapping(value="/", method=RequestMethod.POST)
	public ModelAndView send(
		@RequestParam(value="check1",required=false)boolean check1,
		@RequestParam(value="radio1",required=false)String radio1,
		@RequestParam(value="select1",required=false)String select1,
		@RequestParam(value="select2",required=false)String[] select2,
		ModelAndView mav) {
		
		String res = "";
		try {
			res = "check:" + check1 +
				" radio:" + radio1 +
				" select:" + select1 + 
				"\nselect2:";
		} catch (NullPointerException e) {}
		try {
			res += select2[0];
			for(int i = 1;i < select2.length;i++)
				res += ", " + select2[i];
		} catch (NullPointerException e) {
			res += "null";
		}
		mav.addObject("msg",res);
		mav.setViewName("index");
		return mav;
	}
	
}


リスト3-21
<body>
	<h1>Helo page</h1>
</body>


リスト3-22
package com.tuyano.springboot;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HeloController {
	
	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		return mav;
	}
	@RequestMapping("/other")
	public String other() {
		 return "redirect:/";
	}
	
	@RequestMapping("/home")
	public String home() {
		return "forward:/";
	}

}


リスト4-1
<body>
	<h1>Helo page</h1>
	<p th:text="${new java.util.Date().toString()}"></p>
</body>


リスト4-2
<body>
	<h1>Helo page</h1>
	<p th:text="${#dates.format(new java.util.Date(),'dd/MMM/yyyy HH:mm')}"></p>
	<p th:text="${#numbers.formatInteger(1234,7)}"></p>
	<p th:text="${#strings.toUpperCase('Welcome to Spring.')}"></p>
</body>


リスト4-3
<body>
	<h1>Helo page</h1>
	<p th:text="'from parameter... id=' + ${param.id[0] + ',name=' + param.name[0]}"></p>
</body>


リスト4-4
content.title=message sample page.
content.message=this is sample message from properties.


リスト4-5
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="#{content.message}"></p>
</body>


リスト4-6
content.title=サンプルページ
content.message=これはサンプルで用意したメッセージです。


リスト4-7
content.title=\u30B5\u30F3\u30D7\u30EB\u30DA\u30FC\u30B8
content.message=\u3053\u308C\u306F\u30B5\u30F3\u30D7\u30EB\u3067\u7528\u610F\u3057\u305F\u30E1\u30C3\u30BB\u30FC\u30B8\u3067\u3059\u3002


リスト4-8
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p><a th:href="@{'/home/' + ${param.id[0]}}">link</a></p>
</body>


リスト4-9
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg","current data.");
	DataObject obj = new DataObject(123, "hanako","hanako@flower");
	mav.addObject("object",obj);
	return mav;
}


リスト4-10
<!DOCTYPE HTML>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}">message.</p>
	<table th:object="${object}">
		<tr><th>ID</th><td th:text="*{id}"></td></tr>
		<tr><th>NAME</th><td th:text="*{name}"></td></tr>
		<tr><th>MAIL</th><td th:text="*{value}"></td></tr>
	</table>
</body>
</html>


リスト4-11
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<div th:object="${object}">
		<p th:text="|my name is *{name}. mail address is *{value}.|">message.</p>
	</div>
</body>


リスト4-12
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg","message 1<hr/>message 2<br/>message 3");
	return mav;
}


リスト4-13
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}">message.</p>
</body>


リスト4-14
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:utext="${msg}">message.</p>
</body>


リスト4-15
// import org.springframework.web.bind.annotation.PathVariable; 追加

@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id,
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("id",id);
	mav.addObject("check",id % 2 == 0);
	mav.addObject("trueVal","Even number!");
	mav.addObject("falseVal","Odd number...");
	return mav;
}


リスト4-16
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${id} + ' is ' + (${check} ? ${trueVal} : ${falseVal})"></p>
</body>


リスト4-17
@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id,
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("id",id);
	mav.addObject("check",id >= 0);
	mav.addObject("trueVal","POSITIVE!");
	mav.addObject("falseVal","negative...");
	return mav;
}


リスト4-18
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:if="${check}" th:text="${id} + ' is ' + ${trueVal}">message.</p>
	<p th:unless="${check}" th:text="${id} + ' is ' + ${falseVal}">message.</p>
</body>


リスト4-19
@RequestMapping("/{month}")
public ModelAndView index(@PathVariable int month,
		ModelAndView mav) {
	mav.setViewName("index");
	int m = Math.abs(month) % 12;
	m = m == 0 ? 12 : m;
	mav.addObject("month",m);
	mav.addObject("check",Math.floor(m / 3));
	return mav;
}


リスト4-20
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<div th:switch="${check}">
		<p th:case="0" th:text="|${month} - Winter|"></p>
		<p th:case="1" th:text="|${month} - Spring|"></p>
		<p th:case="2" th:text="|${month} - Summer|"></p>
		<p th:case="3" th:text="|${month} - Autumn|"></p>
		<p th:case="4" th:text="|${month} - Winter|"></p>
		<p th:case="*">...?</p>
	</div>
</body>


リスト4-21
// import java.util.ArrayList; 追加

@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	ArrayList<String[]> data = new ArrayList<String[]>();
	data.add(new String[]{"taro","taro@yamada","090-999-999"});
	data.add(new String[]{"hanako","hanako@flower","080-888-888"});
	data.add(new String[]{"sachiko","sachiko@happy","080-888-888"});
	mav.addObject("data",data);
	return mav;
}


リスト4-22
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<table>
		<tr>
			<th>NAME</th>
			<th>MAIL</th>
			<th>TEL</th>
		</tr>
		<tr th:each="obj:${data}">
			<td th:text="${obj[0]}"></td>
			<td th:text="${obj[1]}"></td>
			<td th:text="${obj[2]}"></td>
		</tr>
	</table>
</body>


リスト4-23
@RequestMapping("/{num}")
public ModelAndView index(@PathVariable int num,
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("num",num);
	if (num >= 0){
		mav.addObject("check","num >= data.size() ? 0 : num");
	} else {
		mav.addObject("check","num <= data.size() * -1 ? 0 : num * -1");
	}
	ArrayList<DataObject> data = new ArrayList<DataObject>();
	data.add(new DataObject(0,"taro","taro@yamada"));
	data.add(new DataObject(1,"hanako","hanako@flower"));
	data.add(new DataObject(2,"sachiko","sachiko@happy"));
	mav.addObject("data",data);
	return mav;
}


リスト4-24
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="|expression[ ${check} ]|"></p>
	<table th:object="${data.get(__${check}__)}">
		<tr><th>ID</th><td th:text="*{id}"></td></tr>
		<tr><th>NAME</th><td th:text="*{name}"></td></tr>
		<tr><th>MAIL</th><td th:text="*{value}"></td></tr>
	</table>
</body>


リスト4-25
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	ArrayList<DataObject> data = new ArrayList<DataObject>();
	data.add(new DataObject(0,"taro","taro@yamada"));
	data.add(new DataObject(1,"hanako","hanako@flower"));
	data.add(new DataObject(2,"sachiko","sachiko@happy"));
	mav.addObject("data",data);
	return mav;
}


リスト4-26
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<table th:inline="text">
		<tr>
		<th>ID</th>
		<th>NAME</th>
		<th>MAIL</th>
		</tr>
		<tr th:each="obj : ${data}">
		<td>[[${obj.id}]]</td>
		<td>[[${obj.name}]]</td>
		<td>[[${obj.value}]]</td>
		</tr>
	</table>
</body>


リスト4-27
@RequestMapping("/{tax}")
public ModelAndView index(@PathVariable int tax,
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("tax",tax);
	return mav;
}


リスト4-28
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	</style>
	<script th:inline="javascript">
	function action(){
		var val = document.getElementById("text1").value;
		var res = parseInt(val * ((100 + /*[[${tax}]]*/) / 100));
		document.getElementById("msg").innerHTML = 
			"include tax: " + res;
	}
	</script>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p id="msg"></p>
	<input type="text" id="text1" />
	<button onclick="action()">click</button>
</body>
</html>


リスト4-29
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>part page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	</style>
	<style th:fragment="frag_style">
	div.fragment {
		border:solid 3px lightgray;
		padding:0px 20px;
	}
	</style>
</head>
<body>
	<h1>Part page</h1>
	<div th:fragment="frag_body">
		<h2>fragment</h2>
		<div class="fragment">
			<p>this is fragment content.</p>
			<p>sample message...</p>
		</div>
	</div>
</body>
</html>


リスト4-30
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	</style>
	<style th:include="part :: frag_style"></style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<div th:include="part :: frag_body">
		<p>this is orginal content.</p>
	</div>
</body>
</html>


リスト4-31
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	return mav;
}


リスト4-32――pom.xmlの場合。<dependencies>内の以下の部分
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>


リスト4-33――build.gradleの場合。dependencies内の以下の部分
compile('org.springframework.boot:spring-boot-starter-thymeleaf')


リスト4-34――pom.xmlの場合
<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
</dependency>


リスト4-35――build.gradleの場合
compile('org.apache.tomcat.embed:tomcat-embed-jasper')


リスト4-36
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp


リスト4-37
<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@ page language="java" 
	contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>JSP Index Page</title>
<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
</style>
</head>
<body>
	<h1>Index page</h1>
	<p>this is JSP sample page.</p>
	<%=new SimpleDateFormat("yyyy年 MM月 dd日").format(new Date()) %>
</body>
</html>


リスト4-38
@RequestMapping("/")
public String index() {
	return "index";
}


リスト4-39
<body>
	<h1>Index page</h1>
	<p>${val}</p>
	<form method="post" action="/">
		<input type="text" name="text1">
		<input type="submit">
	</form>
</body>


リスト4-40
@RequestMapping(value="/", method=RequestMethod.GET)
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("val", "please type...");
	return mav;
}

@RequestMapping(value="/", method=RequestMethod.POST)
public ModelAndView send(@RequestParam String text1,
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("val", "you typed: '" + text1 + "'.");
	return mav;
}


リスト4-41
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-groovy-templates</artifactId>
</dependency>


リスト4-42
compile "org.springframework.boot:spring-boot-starter-groovy-templates"


リスト4-43
html {
	head {
		title('Groovy Page')
		style('''
			h1 { font-size:18pt; font-weight:bold; color:gray; }
			body { font-size:13pt; color:gray; margin:5px 25px; }			
		''')
	}
	body {
		h1('Index Page')
		p('This is Groovy sample page.')
	}
}


リスト4-44
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	return mav;
}


リスト4-45
body {
	h1('Index Page')
	p(msg)
	form(method:'post',action:'/'){
		input(type:'text',name:'num')
		input(type:'submit')
	}
}


リスト4-46
@RequestMapping(value="/", method=RequestMethod.GET)
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg", "type a number...");
	return mav;
}

@RequestMapping(value="/", method=RequestMethod.POST)
public ModelAndView send(@RequestParam int num,
		ModelAndView mav) {
	mav.setViewName("index");
	int total = 0;
	for(int i = 1;i <=num;i++)
		total += i;
	mav.addObject("msg", "total: " + total + " !!");
	return mav;
}


リスト4-47
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg","data table.");
	ArrayList<DataObject> data = new ArrayList<DataObject>();
	data.add(new DataObject(0,"taro","taro@yamada"));
	data.add(new DataObject(1,"hanako","hanako@flower"));
	data.add(new DataObject(2,"sachiko","sachiko@happy"));
	mav.addObject("data",data);
	return mav;
}


リスト4-48
html {
	head {
		title('Groovy Page')
		style('''
			h1 { font-size:18pt; font-weight:bold; color:gray; }
			body { font-size:13pt; color:gray; margin:5px 25px; }			
			tr { margin:5px; }
			th { padding:5px; color:white; background:darkgray; }
			td { padding:5px; color:black; background:#f0f0f0; }
			''')
	}
	body {
		h1('Index Page')
		p(msg)
		table {
			tr {
				th('ID')
				th('NAME')
				th('MAIL')
			}
			data.each{obj ->
				tr {
					td(obj.id)
					td(obj.name)
					td(obj.value)
				}
			}
		}
	}
}


リスト4-49
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

リスト4-50
compile('org.springframework.boot:spring-boot-starter-thymeleaf')


リスト5-1
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>


リスト5-2――HSQLDBの場合
<dependency>
	<groupId>org.hsqldb</groupId>
	<artifactId>hsqldb</artifactId>
</dependency>


リスト5-3――H2の場合
<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
</dependency>


リスト5-4
compile('org.springframework.boot:spring-boot-starter-data-jpa')


リスト5-5――HSQLDBの場合
compile('org.hsqldb:hsqldb')


リスト5-6――H2の場合
compile('com.h2database:h2')


リスト5-7
package com.tuyano.springboot;

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

@Entity
@Table(name="mydata")
public class MyData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	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;
	}
}


リスト5-8
package com.tuyano.springboot.repositories;

public interface MyDataRepository {

}


リスト5-9
package com.tuyano.springboot.repositories;

import com.tuyano.springboot.MyData;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {
	
}


リスト5-10
package com.tuyano.springboot;

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

import com.tuyano.springboot.repositories.MyDataRepository;

@Controller
public class HeloController {
	
	@Autowired
	MyDataRepository repository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","this is sample content.");
		Iterable<MyData> list = repository.findAll();
		mav.addObject("data",list);
		return mav;
	}

}



リスト5-11
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	pre { border: solid 3px #ddd; padding: 10px; }
	</style>
</head>

<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<pre th:text="${data}"></pre>
</body>

</html>


リスト5-12
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	pre { border: solid 3px #ddd; padding: 10px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>

<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<table>
	<form method="post" action="/" th:object="${formModel}">
	<tr><td><label for="name">名前</label></td>
		<td><input type="text" name="name" th:value="*{name}" /></td></tr>
	<tr><td><label for="age">年齢</label></td>
		<td><input type="text" name="age"  th:value="*{age}" /></td></tr>
	<tr><td><label for="mail">メール</label></td>
		<td><input type="text" name="mail"  th:value="*{mail}" /></td></tr>
	<tr><td><label for="memo">メモ</label></td>
	<td><textarea name="memo"  th:text="*{memo}" 
				cols="20" rows="5"></textarea></td></tr>
	<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>ID</th><th>名前</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.name}"></td>
	</tr>
	</table>
</body>

</html>


リスト5-13
package com.tuyano.springboot;

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

import com.tuyano.springboot.repositories.MyDataRepository;

@Controller
public class HeloController {
	
	@Autowired
	MyDataRepository repository;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(
			@ModelAttribute("formModel") MyData mydata, 
			ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","this is sample content.");
		Iterable<MyData> list = repository.findAll();
		mav.addObject("datalist",list);
		return mav;
	}

	@RequestMapping(value = "/", method = RequestMethod.POST)
	@Transactional(readOnly=false)
	public ModelAndView form(
			@ModelAttribute("formModel") MyData mydata, 
			ModelAndView mav) {
		repository.saveAndFlush(mydata);
		return new ModelAndView("redirect:/");
	}

}


リスト5-14
// import javax.annotation.PostConstruct; を追記

@PostConstruct
public void init(){
	MyData d1 = new MyData();
	d1.setName("tuyano");
	d1.setAge(123);
	d1.setMail("syoda@tuyano.com");
	d1.setMemo("this is my data!");
	repository.saveAndFlush(d1);
	MyData d2 = new MyData();
	d2.setName("hanako");
	d2.setAge(15);
	d2.setMail("hanako@flower");
	d2.setMemo("my girl friend.");
	repository.saveAndFlush(d2);
	MyData d3 = new MyData();
	d3.setName("sachiko");
	d3.setAge(37);
	d3.setMail("sachico@happy");
	d3.setMemo("my work friend...");
	repository.saveAndFlush(d3);
}


リスト5-15
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>edit page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="${title}">Edit page</h1>
	<table>
	<form method="post" action="/edit" th:object="${formModel}">
		<input type="hidden" name="id" th:value="*{id}" />
		<tr><td><label for="name">名前</label></td>
			<td><input type="text" name="name" th:value="*{name}" /></td></tr>
		<tr><td><label for="age">年齢</label></td>
			<td><input type="text" name="age"  th:value="*{age}" /></td></tr>
		<tr><td><label for="mail">メール</label></td>
			<td><input type="text" name="mail"  th:value="*{mail}" /></td></tr>
		<tr><td><label for="memo">メモ</label></td>
			<td><textarea name="memo"  th:text="*{memo}" 
			cols="20" rows="5"></textarea></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
</body>
</html>


リスト5-16
package com.tuyano.springboot.repositories;

import com.tuyano.springboot.MyData;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {
	
	public Optional<MyData> findById(Long name);
	
}


リスト5-17
// 以下のimportを追記
// import java.util.Optional;
// import org.springframework.web.bind.annotation.PathVariable;

@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public ModelAndView edit(@ModelAttribute MyData mydata, 
		@PathVariable int id,ModelAndView mav) {
	mav.setViewName("edit");
	mav.addObject("title","edit mydata.");
	Optional<MyData> data = repository.findById((long)id);
	mav.addObject("formModel",data.get());
	return mav;
}

@RequestMapping(value = "/edit", method = RequestMethod.POST)
@Transactional(readOnly=false)
public ModelAndView update(@ModelAttribute MyData mydata, 
		ModelAndView mav) {
	repository.saveAndFlush(mydata);
	return new ModelAndView("redirect:/");
}


リスト5-18
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>edit page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	td { padding:0px 20px; background:#eee;}
	</style>
</head>
<body>
	<h1 th:text="${title}">Edit page</h1>
	<table>
	<form method="post" action="/delete" 
		th:object="${formModel}">
		<input type="hidden" name="id" th:value="*{id}" />
		<tr><td><p th:text="|名前: *{name}|"></p></td></tr>
		<tr><td><p th:text="|年齢: *{age}|" ></p></td></tr>
		<tr><td><p th:text="*{mail}"></p></td></tr>
		<tr><td><p th:text="*{memo}"></p></td></tr>
		<tr><td><input type="submit" value="delete"/></td></tr>
	</form>
	</table>
</body>
</html>


リスト5-19
// import org.springframework.web.bind.annotation.RequestParam; 追加

@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable int id,
		ModelAndView mav) {
	mav.setViewName("delete");
	mav.addObject("title","delete mydata.");
	Optional<MyData> data = repository.findById((long)id);
	mav.addObject("formModel",data.get());
	return mav;
}

@RequestMapping(value = "/delete", method = RequestMethod.POST)
@Transactional(readOnly=false)
public ModelAndView remove(@RequestParam long id, 
		ModelAndView mav) {
	repository.deleteById(id);
	return new ModelAndView("redirect:/");
}


リスト5-20
package com.tuyano.springboot.repositories;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.tuyano.springboot.MyData;

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {
	
	public Optional<MyData> findById(Long name);
	public List<MyData> findByNameLike(String name);
	public List<MyData> findByIdIsNotNullOrderByIdDesc();
	public List<MyData> findByAgeGreaterThan(Integer age);
	public List<MyData> findByAgeBetween(Integer age1, Integer age2);

}


リスト5-21
package jp.springbook.springmyapp;

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

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "mydata")
public class MyData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull	// ●
	private long id;

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

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

	@Column(nullable = true)
	@Min(0)	// ●
	@Max(200) // ●
	private Integer age;

	@Column(nullable = true)
	private String memo;

	……アクセサは省略……
}


リスト5-22
// 以下のimport文を追記
// import org.springframework.validation.BindingResult;
// import org.springframework.validation.annotation.Validated;

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(
	@ModelAttribute("formModel") MyData mydata, 
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg","this is sample content.");
	mav.addObject("formModel",mydata);
	Iterable<MyData> list = repository.findAll();
	mav.addObject("datalist",list);
	return mav;
}

@RequestMapping(value = "/", method = RequestMethod.POST)
@Transactional(readOnly=false)
public ModelAndView form(
		@ModelAttribute("formModel") 
		@Validated MyData mydata,
		BindingResult result,
		ModelAndView mov) {
	ModelAndView res = null;
	if (!result.hasErrors()){
		repository.saveAndFlush(mydata);
		res = new ModelAndView("redirect:/");
	} else {
		mov.setViewName("index");
		mov.addObject("msg","sorry, error is occured...");
		Iterable<MyData> list = repository.findAll();
		mov.addObject("datalist",list);
		res = mov;
	}
	return res;
}


リスト5-23
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	.err { color:red; }
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form method="post" action="/" th:object="${formModel}">
		<ul>
			<li th:each="error : ${#fields.detailedErrors()}"
				class="err" th:text="${error.message}" />
		</ul>
		<tr><td><label for="name">名前</label></td>
			<td><input type="text" name="name" 
				th:field="*{name}" /></td></tr>
		<tr><td><label for="age">年齢</label></td>
			<td><input type="text" name="age"
				th:field="*{age}" /></td></tr>
		<tr><td><label for="mail">メール</label></td>
			<td><input type="text" name="mail" 
					th:field="*{mail}" /></td></tr>
		<tr><td><label for="memo">メモ</label></td>
			<td><textarea name="memo" th:field="*{memo}" 
				cols="20" rows="5" ></textarea></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>ID</th><th>名前</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.name}"></td>
	</tr>
	</table>
</body>
</html>


リスト5-24
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form method="post" action="/" th:object="${formModel}">
		<tr><td><label for="name">名前</label></td>
			<td><input type="text" name="name"
				th:value="*{name}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('name')}" 
				th:errors="*{name}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="age">年齢</label></td>
			<td><input type="text" name="age"
				th:value="*{age}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('age')}" 
				th:errors="*{age}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="mail">メール</label></td>
			<td><input type="text" name="mail" 
				th:value="*{mail}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('mail')}" 
				th:errors="*{mail}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="memo">メモ</label></td>
			<td><textarea name="memo" th:text="*{memo}" 
				cols="20" rows="5" ></textarea></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>ID</th><th>名前</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.name}"></td>
	</tr>
	</table>
</body>


リスト5-25
@Entity
@Table(name="mydata")
public class MyData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull	// ●
	private long id;

	@Column(length = 50, nullable = false)
	@NotEmpty(message="空白は不可")	// ●
	private String name;

	@Column(length = 200, nullable = true)
	@Email(message="メールアドレスのみ")	// ●
	private String mail;

	@Column(nullable = true)
	@Min(value=0,message="ゼロ以上")	// ●
	@Max(value=200,message="200以下") // ●
	private Integer age;

	@Column(nullable = true)
	private String memo;

	……以下略……
}


リスト5-26
org.hibernate.validator.constraints.NotBlank.message = 空白は不可です。
org.hibernate.validator.constraints.NotEmpty.message = 空白は不可です。
javax.validation.constraints.Max.message = {value} より小さくして下さい。
javax.validation.constraints.Min.message = {value} より大きくして下さい。
org.hibernate.validator.constraints.Email.message = メールアドレスではありません。


リスト5-27
org.hibernate.validator.constraints.NotBlank.message = \u7A7A\u767D\u306F\u4E0D\u53EF\u3067\u3059\u3002
org.hibernate.validator.constraints.NotEmpty.message = \u7A7A\u767D\u306F\u4E0D\u53EF\u3067\u3059\u3002
javax.validation.constraints.Max.message = {value} \u3088\u308A\u5C0F\u3055\u304F\u3057\u3066\u4E0B\u3055\u3044\u3002
javax.validation.constraints.Min.message = {value} \u3088\u308A\u5927\u304D\u304F\u3057\u3066\u4E0B\u3055\u3044\u3002
org.hibernate.validator.constraints.Email.message = \u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002


リスト5-28
package com.tuyano.springboot;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class PhoneValidator implements ConstraintValidator<Phone, String> {

	@Override
	public void initialize(Phone phone) {
	}

	@Override
	public boolean isValid(String input, ConstraintValidatorContext cxt) {
		if (input == null) {
			return false;
		}
		return input.matches("[0-9()-]*");
	}

}


リスト5-29
package com.tuyano.springboot;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;

@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface Phone {

	String message() default "please input a phone number.";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

}


リスト5-30
@Column(nullable = true)
@Phone
private String memo;


リスト5-31
<tr><td><label for="memo">メモ</label></td>
	<td><textarea name="memo" th:text="*{memo}" 
		th:errorclass="err" cols="20" rows="5" ></textarea>
	<div th:if="${#fields.hasErrors('memo')}" 
		th:errors="*{memo}" th:errorclass="err"></div></td></tr>


リスト5-32
@PostConstruct
public void init(){
	MyData d1 = new MyData();
	d1.setName("tuyano");
	d1.setAge(123);
	d1.setMail("syoda@tuyano.com");
	d1.setMemo("090-999-999"); // ●
	repository.saveAndFlush(d1);
	MyData d2 = new MyData();
	d2.setName("hanako");
	d2.setAge(15);
	d2.setMail("hanako@flower");
	d2.setMemo("080-888-888"); // ●
	repository.saveAndFlush(d2);
	MyData d3 = new MyData();
	d3.setName("sachiko");
	d3.setAge(37);
	d3.setMail("sachico@happy");
	d3.setMemo("070-777-777"); // ●
	repository.saveAndFlush(d3);
}


リスト5-33
public @interface Phone {

	String message() default "please input a phone number.";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

	boolean onlyNumber() default false;	// ●
	
}


リスト5-34
public class PhoneValidator implements ConstraintValidator<Phone, String> {
	private boolean onlyNumber = false;

	@Override
	public void initialize(Phone phone) {
		onlyNumber = phone.onlyNumber();
	}

	@Override
	public boolean isValid(String input, ConstraintValidatorContext cxt) {
		if (input == null) {
			return false;
		}
		if (onlyNumber) {
			return input.matches("[0-9]*");
		} else {
			return input.matches("[0-9()-]*");
		}
	}

}


リスト5-35
@Column(nullable = true)
@Phone(onlyNumber=true)
private String memo;


リスト5-36――initメソッドの修正
@PostConstruct
public void init(){
	MyData d1 = new MyData();
	d1.setName("tuyano");
	d1.setAge(123);
	d1.setMail("syoda@tuyano.com");
	d1.setMemo("090999999"); // ●
	repository.saveAndFlush(d1);
	MyData d2 = new MyData();
	d2.setName("hanako");
	d2.setAge(15);
	d2.setMail("hanako@flower");
	d2.setMemo("080888888"); // ●
	repository.saveAndFlush(d2);
	MyData d3 = new MyData();
	d3.setName("sachiko");
	d3.setAge(37);
	d3.setMail("sachico@happy");
	d3.setMemo("070777777"); // ●
	repository.saveAndFlush(d3);
}


リスト6-1
package com.tuyano.springboot;

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

public interface MyDataDao <T> extends Serializable {
	
	public List<T> getAll();
	
}


リスト6-2
package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

@Repository
public class MyDataDaoImpl implements MyDataDao<MyData> {
	private static final long serialVersionUID = 1L;
	
	private EntityManager entityManager;
	
	public MyDataDaoImpl(){
		super();
	}
	public MyDataDaoImpl(EntityManager manager){
		this();
		entityManager = manager;
	}
	
	@Override
	public List<MyData> getAll() {
		Query query = entityManager.createQuery("from MyData");
		@SuppressWarnings("unchecked")
		List<MyData> list = query.getResultList();
		entityManager.close();
		return list;
	}
	
}


リスト6-3
package com.tuyano.springboot;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.tuyano.springboot.repositories.MyDataRepository;

@Controller
public class HeloController {
	
	@Autowired
	MyDataRepository repository;
	
	@PersistenceContext
	EntityManager entityManager; //●
	
	MyDataDaoImpl dao; //●
	
	@PostConstruct
	public void init(){
		dao = new MyDataDaoImpl(entityManager); //●
		MyData d1 = new MyData();
		d1.setName("tuyano");
		d1.setAge(123);
		d1.setMail("syoda@tuyano.com");
		d1.setMemo("090999999");
		repository.saveAndFlush(d1);
		MyData d2 = new MyData();
		d2.setName("hanako");
		d2.setAge(15);
		d2.setMail("hanako@flower");
		d2.setMemo("080888888");
		repository.saveAndFlush(d2);
		MyData d3 = new MyData();
		d3.setName("sachiko");
		d3.setAge(37);
		d3.setMail("sachico@happy");
		d3.setMemo("070777777");
		repository.saveAndFlush(d3);
	}

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","MyDataのサンプルです。");
		Iterable<MyData> list = dao.getAll(); //●
		mav.addObject("datalist", list);
		return mav;
	}

}


リスト6-4
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	.err { color:red; }
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}"></p>
	<table>
	<tr><th>ID</th><th>名前</th><th>メール</th><th>年齢</th><th>メモ(tel)</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.name}"></td>
		<td th:text="${obj.mail}"></td>
		<td th:text="${obj.age}"></td>
		<td th:text="${obj.memo}"></td>
	</tr>
	</table>
</body>
</html>


リスト6-5
package jp.springbook.springmyapp;

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

public interface MyDataDao<T> extends Serializable {
	
	public List<T> getAll();
	public T findById(long id); // ●
	public List<T> findByName(String name); // ●
}


リスト6-6
@Override
public MyData findById(long id) {
	return (MyData)entityManager.createQuery("from MyData where id = " 
		+ id).getSingleResult();
}

@SuppressWarnings("unchecked")
@Override
public List<MyData> findByName(String name) {
	return (List<MyData>)entityManager.createQuery("from MyData where name = " 
		+ name).getResultList();
}


リスト6-7
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>find page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="${title}">find page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form action="/find" method="post">
		<tr><td>FIND:</td>
		<td><input type="text" name="fstr" size="20" 
			th:value="${value}"/></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>ID</th><th>名前</th>
		<th>メール</th><th>年齢</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.name}"></td>
		<td th:text="${obj.mail}"></td>
		<td th:text="${obj.age}"></td>
	</tr>
	</table>
</body>
</html>


リスト6-8
// 以下のimport文を追記
// import java.util.List;
// import javax.servlet.http.HttpServletRequest; 

@RequestMapping(value = "/find", method = RequestMethod.GET)
public ModelAndView find(ModelAndView mav) {
	mav.setViewName("find");
	mav.addObject("title","Find Page");
	mav.addObject("msg","MyDataのサンプルです。");
	mav.addObject("value","");
	Iterable<MyData> list = dao.getAll(); //●
	mav.addObject("datalist", list);
	return mav;
}

@RequestMapping(value = "/find", method = RequestMethod.POST)
public ModelAndView search(HttpServletRequest request,
		ModelAndView mav) {
	mav.setViewName("find");
	String param = request.getParameter("fstr");
	if (param == ""){
		mav = new ModelAndView("redirect:/find");
	} else {
		mav.addObject("title","Find result");
		mav.addObject("msg","「" + param + "」の検索結果");
		mav.addObject("value",param);
		List<MyData> list = dao.find(param);
		mav.addObject("datalist", list);
	}
	return mav;
}


リスト6-9
public List<T> find(String fstr);


リスト6-10
@Override
public List<MyData> find(String fstr){
	List<MyData> list = null;
	String qstr = "from MyData where id = :fstr";
	Query query = entityManager.createQuery(qstr)
		.setParameter("fstr", Long.parseLong(fstr));
	list = query.getResultList();
	return list;
}


リスト6-11
@SuppressWarnings("unchecked")
@Override
public List<MyData> find(String fstr){
	List<MyData> list = null;
	String qstr = "from MyData where id = :fid or name like :fname or mail like :fmail";
	Long fid = 0L;
	try {
		fid = Long.parseLong(fstr);
	} catch (NumberFormatException e) {
		e.printStackTrace();
	}
	Query query = entityManager.createQuery(qstr).setParameter("fid", fid)
			.setParameter("fname", "%" + fstr + "%")
			.setParameter("fmail", fstr + "@%");
	list = query.getResultList();
	return list;
}


リスト6-12
@SuppressWarnings("unchecked")
@Override
public List<MyData> find(String fstr){
	List<MyData> list = null;
	String qstr = "from MyData where id = ?1 or name like ?2 or mail like ?3";
	Long fid = 0L;
	try {
		fid = Long.parseLong(fstr);
	} catch (NumberFormatException e) {
		e.printStackTrace();
	}
	Query query = entityManager.createQuery(qstr).setParameter(1, fid)
		.setParameter(2, "%" + fstr + "%")
		.setParameter(3, fstr + "@%");
	list = query.getResultList();
	return list;
}


リスト6-13
// import javax.persistence.NamedQuery; を追加

@NamedQuery(
	name="findWithName",
	query="from MyData where name like :fname"
)


リスト6-14
@NamedQueries (
	@NamedQuery(
		name="findWithName",
		query="from MyData where name like :fname"
	)
)


リスト6-15
@SuppressWarnings("unchecked")
@Override
public List<MyData> find(String fstr){
	List<MyData> list = null;
	Long fid = 0L;
	try {
		fid = Long.parseLong(fstr);
	} catch (NumberFormatException e) {
		//e.printStackTrace();
	}
	Query query = entityManager
			.createNamedQuery("findWithName")
			.setParameter("fname", "%" + fstr + "%");
	list = query.getResultList();
	return list;
}


リスト6-16
package com.tuyano.springboot.repositories;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import com.tuyano.springboot.MyData;

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {
	
	@Query("SELECT d FROM MyData d ORDER BY d.name")
	List<MyData> findAllOrderByName();
}


リスト6-17
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("title","Find Page");
	mav.addObject("msg","MyDataのサンプルです。");
	Iterable<MyData> list = repository.findAllOrderByName(); //dao.getAll(); //●
	mav.addObject("datalist", list);
	return mav;
}


リスト6-18
@NamedQuery(
	name="findByAge",
	query="from MyData where age > :min and age < :max"
)


リスト6-19	MyDataDaoに追記
public List<MyData> findByAge(int min, int max);


リスト6-20	MyDataDaoImplに追記
@SuppressWarnings("unchecked")
@Override
public List<MyData> findByAge(int min, int max) {
	return (List<MyData>)entityManager
		.createNamedQuery("findByAge")
		.setParameter("min", min)
		.setParameter("max", max)
		.getResultList();
}


リスト6-21
// import org.springframework.data.repository.query.Param; 追記

@Query("from MyData where age > :min and age < :max")
public List<MyData> findByAge(@Param("min") int min, @Param("max") int max);


リスト6-22
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;


リスト6-23
@Override
public List<MyData> getAll() {
	List<MyData> list = null;		
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
			builder.createQuery(MyData.class);
	Root<MyData> root = query.from(MyData.class);
	query.select(root);
	list = (List<MyData>)entityManager
			.createQuery(query)
			.getResultList();
	return list;
}


リスト6-24
@Override
public List<MyData> find(String fstr){
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
		builder.createQuery(MyData.class);
	Root<MyData> root = 
		query.from(MyData.class);
	query.select(root)
		.where(builder.equal(root.get("name"), fstr));
	List<MyData> list = null;
	list = (List<MyData>) entityManager
			.createQuery(query)
			.getResultList();
	return list;
}


リスト6-25
@Override
public List<MyData> getAll() {
	List<MyData> list = null;		
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
			builder.createQuery(MyData.class);
	Root<MyData> root = query.from(MyData.class);
	query.select(root)
			.orderBy(builder.asc(root.get("name")));
	list = (List<MyData>)entityManager
			.createQuery(query)
			.getResultList();
	return list;
}


リスト6-26
@Override
public List<MyData> getAll() {
	int offset = 1; // ●取り出す位置の指定
	int limit = 2; // ●取り出す個数の指定
	List<MyData> list = null;
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
			builder.createQuery(MyData.class);
	Root<MyData> root = 
			query.from(MyData.class);
	query.select(root);
	list = (List<MyData>)entityManager
			.createQuery(query)
			.setFirstResult(offset)
			.setMaxResults(limit)
			.getResultList();
	return list;
}


リスト6-27――MsgData.java
package com.tuyano.springboot;

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

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "msgdata")
public class MsgData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column
	private String title;

	@Column(nullable = false)
	@NotEmpty
	private String message;

	@ManyToOne
	private MyData mydata;

	public MsgData() {
		super();
		mydata = new MyData();
	}

	public long getId() {
		return id;
	}

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

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public MyData getMydata() {
		return mydata;
	}

	public void setMydata(MyData mydata) {
		this.mydata = mydata;
	}
}


リスト6-28
// 以下のimportを追加
// import java.util.List;
// import javax.persistence.CascadeType;
// import javax.persistence.OneToMany;

@Entity
@Table(name = "mydata")
public class MyData {
	
	// 以下のフィールドとメソッドを追加
	@OneToMany(cascade=CascadeType.ALL)
	@Column(nullable = true)
	private List<MsgData> msgdatas;
	
	public List<MsgData> getMsgdatas() {
		return msgdatas;
	}

	public void setMsgdatas(List<MsgData> msgdatas) {
		this.msgdatas = msgdatas;
	}
	
	……その他のものは変更しないので省略……	
}


リスト6-29――MsgDataRepository.java
package com.tuyano.springboot.repositories;

import org.springframework.data.jpa.repository.JpaRepository;

import com.tuyano.springboot.MsgData;

public interface MsgDataRepository 
	extends JpaRepository<MsgData, Long> {
	
}


リスト6-30――MsgDataDao.java
package com.tuyano.springboot;

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

public interface MsgDataDao<T> {
	
	public List<MsgData> getAll();
	public MsgData findById(long id);

}


リスト6-31――MsgDataDaoImpl.java
package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;

@SuppressWarnings("rawtypes")
public class MsgDataDaoImpl implements MsgDataDao<MsgDataDao> {

	private EntityManager entityManager;
	
	public MsgDataDaoImpl(){
		super();
	}
	public MsgDataDaoImpl(EntityManager manager){
		entityManager = manager;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<MsgData> getAll() {
		return entityManager
				.createQuery("from MsgData")
				.getResultList();
	}

	@Override
	public MsgData findById(long id) {
		return (MsgData)entityManager
				.createQuery("from MsgData where id = " 
				+ id).getSingleResult();
	}
}


リスト6-32――showMsgData.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title th:text="${title}">top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="${title}">MyMsg page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form method="post" action="/msg" 
			th:object="${formModel}">
		<input type="hidden" name="id" th:value="*{id}" />
		<tr><td><label for="title">タイトル</label></td>
			<td><input type="text" name="title" 
				th:value="*{title}" /></td></tr>
		<tr><td><label for="message">メッセージ</label></td>
			<td><textarea name="message"  
				th:text="*{message}"></textarea></td></tr>
		<tr><td><label for="mydata">MYDATA_ID</label></td>
			<td><input type="text" name="mydata" /></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>ID</th><th>名前</th><th>タイトル</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.id}"></td>
		<td th:text="${obj.mydata.name}"></td>
		<td th:text="${obj.title}"></td>
	</tr>
	</table>
</body>
</html>


リスト6-33
package com.tuyano.springboot;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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;
import org.springframework.web.servlet.ModelAndView;

import com.tuyano.springboot.repositories.MsgDataRepository;

@Controller
public class MsgDataController {
	
	@Autowired
	MsgDataRepository repository;
	
	@PersistenceContext
	EntityManager entityManager;
	
	MsgDataDaoImpl dao;

	@RequestMapping(value = "/msg", method = RequestMethod.GET)
	public ModelAndView msg(ModelAndView mav) {
		mav.setViewName("showMsgData");
		mav.addObject("title","Sample");
		mav.addObject("msg","MsgDataのサンプルです。");
		MsgData msgdata = new MsgData();
		mav.addObject("formModel", msgdata);
		List<MsgData> list = (List<MsgData>)dao.getAll();
		mav.addObject("datalist", list);
		return mav;
	}

	@RequestMapping(value = "/msg", method = RequestMethod.POST)
	public ModelAndView msgform(
			@Valid @ModelAttribute MsgData msgdata, 
			Errors result, 
			ModelAndView mav) {
		if (result.hasErrors()) {
			mav.setViewName("showMsgData");
			mav.addObject("title", "Sample [ERROR]");
			mav.addObject("msg", "値を再チェックしてください!");
			return mav;
		} else {
			repository.saveAndFlush(msgdata);
			return new ModelAndView("redirect:/msg");
		}
	}

	@PostConstruct
	public void init(){
		System.out.println("ok");
		dao = new MsgDataDaoImpl(entityManager);
	}

}


リスト7-1
package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Service;

@Service
public class MyDataService {

	@PersistenceContext
	private EntityManager entityManager;

	@SuppressWarnings("unchecked")
	public List<MyData> getAll() {
		return (List<MyData>) entityManager
			.createQuery("from MyData").getResultList();
	}

	public MyData get(int num) {
		return (MyData)entityManager
				.createQuery("from MyData where id = " + num)
				.getSingleResult();
	}

	public List<MyData> find(String fstr) {
		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.equal(root.get("name"), fstr));
		List<MyData> list = null;
		list = (List<MyData>) entityManager.createQuery(query).getResultList();
		return list;
	}

}


リスト7-2
package com.tuyano.springboot;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

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.servlet.ModelAndView;

import com.tuyano.springboot.repositories.MyDataRepository;

@Controller
public class HeloController {
	
	@Autowired
	MyDataRepository repository;
	
	@Autowired
	private MyDataService service;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("title","Find Page");
		mav.addObject("msg","MyDataのサンプルです。");
		List<MyData> list = service.getAll(); //●
		mav.addObject("datalist", list);
		return mav;
	}
	
	@RequestMapping(value = "/find", method = RequestMethod.GET)
	public ModelAndView find(ModelAndView mav) {
		mav.setViewName("find");
		mav.addObject("title","Find Page");
		mav.addObject("msg","MyDataのサンプルです。");
		mav.addObject("value","");
		List<MyData> list = service.getAll(); //●
		mav.addObject("datalist", list);
		return mav;
	}
	
	@RequestMapping(value = "/find", method = RequestMethod.POST)
	public ModelAndView search(HttpServletRequest request,
			ModelAndView mav) {
		mav.setViewName("find");
		String param = request.getParameter("fstr");
		if (param == ""){
			mav = new ModelAndView("redirect:/find");
		} else {
			mav.addObject("title","Find result");
			mav.addObject("msg","「" + param + "」の検索結果");
			mav.addObject("value",param);
			List<MyData> list = service.find(param); //●
			mav.addObject("datalist", list);
		}
		return mav;
	}

	@PostConstruct
	public void init(){
		d1.setName("tuyano");
		d1.setAge(123);
		d1.setMail("syoda@tuyano.com");
		d1.setMemo("090999999");
		repository.saveAndFlush(d1);

		……必要なだけダミーデータを用意……

	}

}


リスト7-3
package com.tuyano.springboot;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyDataRestController {

	@Autowired
	private MyDataService service;

	@RequestMapping("/rest")
	public List<MyData> restAll() {
		return service.getAll();
	}

	@RequestMapping("/rest/{num}")
	public MyData restBy(@PathVariable int num) {
		return service.get(num);
	}
}


リスト7-4
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
	<script th:inline="javascript">
	$(document).ready(function(){
		var num = /*[[${param.id[0]}]]*/;
		$.get("/rest/" + num, null, callback);
	});
	function callback(result){
		$('#obj').append('<li>id: ' + result.id + '</li>');
		$('#obj').append('<li>name: ' + result.name + '</li>');
		$('#obj').append('<li>mail: ' + result.mail + '</li>');
		$('#obj').append('<li>age: ' + result.age + '</li>');
		$('#obj').append('<li>memo: ' + result.memo + '</li>');
	}
	</script>
	<style>
	……略……
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p  th:text="${msg}"></p>
	<ol id="obj"></ol>
	<table>
	……略……
	</table>
</body>
</html>


リスト7-5
<dependency>
	<groupId>com.fasterxml.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>


リスト7-6
compile('com.fasterxml.jackson.dataformat:jackson-dataformat-xml')


リスト7-7
package com.tuyano.springboot;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;

@Component
public class MySampleBean {
	private int counter = 0;
	private int max = 10;

	@Autowired
	public MySampleBean(ApplicationArguments args) {
		List<String> files = args.getNonOptionArgs();
		try {
			max = Integer.parseInt(files.get(0));
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}

	public int count() {
		counter++;
		counter = counter > max ? 0 : counter;
		return counter;
	}
}


リスト7-8
public static void main(String[] args) {
	SpringApplication.run(
			MyBootAppApplication.class, 
			new String[]{"100"});
}


リスト7-9
@Autowired
MySampleBean bean;

@RequestMapping("/count")
public int count() {
	return bean.count();
}


リスト7-10
package com.tuyano.springboot;

import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBootAppConfig {
}


リスト7-11
package com.tuyano.springboot;

import org.springframework.beans.factory.annotation.Autowired;

import com.tuyano.springboot.repositories.MyDataRepository;

public class MyDataBean {
	
	@Autowired
	MyDataRepository repository;
	
	public String getTableTagById(Long id){
		Optional<MyData> opt = repository.findById(id);
		MyData data = opt.get();
		String result = "<tr><td>" + data.getName()
				+ "</td><td>" + data.getMail() + 
				"</td><td>" + data.getAge() + 
				"</td><td>" + data.getMemo() + 
				"</td></tr>";
		return result;
	}

}


リスト7-12
package com.tuyano.springboot;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBootAppConfig {

	@Bean
	MyDataBean myDataBean(){
		return new MyDataBean();
	}
}


リスト7-13
// import org.springframework.web.bind.annotation.PathVariable; 追加

@Autowired
MyDataBean myDataBean;

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView indexById(@PathVariable long id,
		ModelAndView mav) {
	mav.setViewName("pickup");
	mav.addObject("title","Pickup Page");
	String table = "<table>"
			+ myDataBean.getTableTagById(id)
			+ "</table>";
	mav.addObject("msg","pickup data id = " + id);
	mav.addObject("data",table);
	return mav;
}


リスト7-14
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}"></p>
	<p th:utext="${data}"></p>
</body>
</html>


リスト7-15
// 以下のimportを追加
// import org.springframework.data.domain.Page;
// import org.springframework.data.domain.Pageable;

public Page<MyData> findAll(Pageable pageable);


リスト7-16
@RequestMapping(value = "/page", method = RequestMethod.GET)
public ModelAndView index(ModelAndView mav, Pageable pageable) {
	mav.setViewName("index");
	mav.addObject("title","Find Page");
	mav.addObject("msg","MyDataのサンプルです。");
	Page<MyData> list = repository.findAll(pageable); //●
	mav.addObject("datalist", list);
	return mav;
}


リスト7-17
<table>
<tr><th>ID</th><th>名前</th><th>メール</th><th>年齢</th><th>メモ(tel)</th></tr>
<tr th:each="obj : ${datalist}">
	<td th:text="${obj.id}"></td>
	<td th:text="${obj.name}"></td>
	<td th:text="${obj.mail}"></td>
	<td th:text="${obj.age}"></td>
	<td th:text="${obj.memo}"></td>
</tr>
</table>


リスト7-18
package com.tuyano.springboot;

import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.AttributeName;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressions;
import org.thymeleaf.templatemode.TemplateMode;

public class MyPageAttributeTagProcessor extends AbstractAttributeTagProcessor {
	
	private static final String ATTR_NAME = "mypage";
	private static final int PRECEDENCE = 10000;
	public static int size = 2;

	public MyPageAttributeTagProcessor(final String dialectPrefix) {
		super(TemplateMode.HTML, dialectPrefix, null,
				false, ATTR_NAME, true, PRECEDENCE, true);
    }
	 
	protected MyPageAttributeTagProcessor(TemplateMode templateMode, 
			String dialectPrefix, String elementName,
			boolean prefixElementName, 
			String attributeName, 
			boolean prefixAttributeName, 
			int precedence,
			boolean removeAttribute) {
		super(templateMode, dialectPrefix, elementName, 
				prefixElementName, attributeName, prefixAttributeName, 
				precedence,removeAttribute);
	}

	@Override
	protected void doProcess(ITemplateContext context, 
			IProcessableElementTag tag, 
			AttributeName attrName, 
			String attrValue,
			IElementTagStructureHandler handler) {
		
		final IEngineConfiguration configuration = context.getConfiguration();
		final IStandardExpressionParser parser =
				StandardExpressions.getExpressionParser(configuration);
		final IStandardExpression expression = 
				parser.parseExpression(context, attrValue);
		int value = (int)expression.execute(context);
		value = value < 0 ? 0 : value;
		handler.setAttribute("href", "/page?size=" + size + "&page=" + value);
	}

}


リスト7-19
package com.tuyano.springboot;

import java.util.HashSet;
import java.util.Set;

import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
import org.thymeleaf.standard.StandardDialect;

public class MyDialect extends AbstractProcessorDialect {
	
	private static final String DIALECT_NAME = "My Dialect";
	
	public MyDialect() {
		super(DIALECT_NAME, "my", StandardDialect.PROCESSOR_PRECEDENCE);
	}
	protected MyDialect(String name, String prefix, 
			int processorPrecedence) {
		super(name, prefix, processorPrecedence);
	}

	@Override
	public Set<IProcessor> getProcessors(String dialectPrefix) {
		final Set<IProcessor> processors = new HashSet<IProcessor>();
		processors.add(new MyPageAttributeTagProcessor(dialectPrefix));
		return processors;
	}

}


リスト7-20 MyBootAppConfig
// 以下のimort文を追加
// import org.thymeleaf.spring5.SpringTemplateEngine;
// import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Bean
public ClassLoaderTemplateResolver templateResolver() {
	ClassLoaderTemplateResolver templateResolver = 
			new ClassLoaderTemplateResolver();
	templateResolver.setPrefix("templates/");
	templateResolver.setCacheable(false);
	templateResolver.setSuffix(".html");        
	templateResolver.setTemplateMode("HTML5");
	templateResolver.setCharacterEncoding("UTF-8");
	return templateResolver;
}
 
@Bean
public SpringTemplateEngine templateEngine(){
	SpringTemplateEngine templateEngine = new SpringTemplateEngine();
	templateEngine.setTemplateResolver(templateResolver());
	templateEngine.addDialect(new MyDialect());
	return templateEngine;
}


リスト7-21
<div>
<a my:mypage="${datalist.getNumber() - 1}">&lt;&lt;prev</a>
|
<a my:mypage="${datalist.getNumber() + 1}">next&gt;&gt;</a>
</div>


リスト7-22
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>


リスト7-23
compile('org.springframework.boot:spring-boot-starter-data-mongodb')


リスト7-24
package com.tuyano.springboot;

import java.util.Date;

import org.springframework.data.annotation.Id;

public class MyDataMongo {
	@Id
	private String id;
     
	private String name;
	private String memo;
	private Date date;
    
	public MyDataMongo(String name, String memo) {
    		super();
	    	this.name = name;
    		this.memo = memo;
    		this.date = new Date();
	}
    
	public String getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getMemo() {
		return memo;
	}
	public Date getDate() {
		return date;
	}
}


リスト7-25
package com.tuyano.springboot.repositories;

import org.springframework.data.mongodb.repository.MongoRepository;

import com.tuyano.springboot.MyDataMongo;

public interface MyDataMongoRepository 
		extends MongoRepository<MyDataMongo, Long> {

}


リスト7-26
package com.tuyano.springboot;

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

import com.tuyano.springboot.repositories.MyDataMongoRepository;

@Controller
public class HeloController {
	
	@Autowired
	MyDataMongoRepository repository;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("title","Find Page");
		mav.addObject("msg","MyDataMongoのサンプルです。");
		Iterable<MyDataMongo> list = repository.findAll();
		mav.addObject("datalist", list);
		return mav;
	}
	
	@RequestMapping(value = "/", method = RequestMethod.POST)
	@Transactional(readOnly=false)
	public ModelAndView form(
			@RequestParam("name") String name,
			@RequestParam("memo") String memo,
			ModelAndView mov) {
		MyDataMongo mydata = new MyDataMongo(name,memo);
		repository.save(mydata);
		return new ModelAndView("redirect:/");
	}
	
}


リスト7-27
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>top page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	table.navi {width:100%; background:white; }
	table.navi tr { background:white; }
	table.navi tr td { background:white; }
	.err { color:red; }
	</style>
</head>
<body>
	<h1 th:text="#{content.title}">Helo page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form method="post" action="/">
	<tr><td><label for="name">名前</label></td>
		<td><input type="text" name="name" /></td></tr>
	<tr><td><label for="memo">メモ</label></td>
	<td><textarea name="memo" 
				cols="20" rows="5"></textarea></td></tr>
	<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>名前</th><th>メモ</th><th>日時</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.name}"></td>
		<td th:text="${obj.memo}"></td>
		<td th:text="${obj.date}"></td>
	</tr>
	</table>
</body>
</html>


リスト7-28
// import java.util.List; 追加
public List<MyDataMongo> findByName(String s);


リスト7-29
// import java.util.List; 追加

@RequestMapping(value = "/find", method = RequestMethod.GET)
public ModelAndView find(ModelAndView mav) {
	mav.setViewName("find");
	mav.addObject("title","Find Page");
	mav.addObject("msg","MyDataのサンプルです。");
	mav.addObject("value","");
	List<MyDataMongo> list = repository.findAll();
	mav.addObject("datalist", list);
	return mav;
}

@RequestMapping(value = "/find", method = RequestMethod.POST)
public ModelAndView search(
		@RequestParam("find") String param,
		ModelAndView mav) {
	mav.setViewName("find");
	if (param == ""){
		mav = new ModelAndView("redirect:/find");
	} else {
		mav.addObject("title","Find result");
		mav.addObject("msg","「" + param + "」の検索結果");
		mav.addObject("value",param);
		List<MyDataMongo> list = repository.findByName(param);
		mav.addObject("datalist", list);
	}
	return mav;
}


リスト7-30
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>find page</title>
	<meta http-equiv="Content-Type" 
		content="text/html; charset=UTF-8" />
	<style>
	h1 { font-size:18pt; font-weight:bold; color:gray; }
	body { font-size:13pt; color:gray; margin:5px 25px; }
	tr { margin:5px; }
	th { padding:5px; color:white; background:darkgray; }
	td { padding:5px; color:black; background:#f0f0f0; }
	</style>
</head>
<body>
	<h1 th:text="${title}">find page</h1>
	<p th:text="${msg}"></p>
	<table>
	<form action="/find" method="post">
		<tr><td>検索:</td>
		<td><input type="text" name="find" size="20" 
			th:value="${value}"/></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
	<hr/>
	<table>
	<tr><th>名前</th><th>メモ</th><th>日時</th></tr>
	<tr th:each="obj : ${datalist}">
		<td th:text="${obj.name}"></td>
		<td th:text="${obj.memo}"></td>
		<td th:text="${obj.date}"></td>
	</tr>
	</table>
</body>
</html>


f:id:kobayashi8286:20180603142550p:plain f:id:kobayashi8286:20180603142553p:plain f:id:kobayashi8286:20180603142556p:plain f:id:kobayashi8286:20180603142546p:plain f:id:kobayashi8286:20180603142547p:plain f:id:kobayashi8286:20180603142341p:plain f:id:kobayashi8286:20180603142537p:plain

application.properties/yml

|| spring: datasource: url: jdbc:mysql://localhost/test username: Owner password: driverClassName: com.mysql.jdbc.Driver ||<

boot

package com.tuyano.springboot;

import java.util.Optional;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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 org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.tuyano.springboot.repositories.MyDataRepository;

//@RestController

//public class HeloController {
//for 1
		// public String index() {
		//return "Hello Spring-Boot World!!";
		//}
//for 2
		//	@RequestMapping("/{num}")
		//	public String index(@PathVariable int num) {
		//		int res = 0;
		//		for(int i = 1; i<=num;i++) {
		//			res += i;
		//		}
		//			return "total " + res;
		//	}
//for 3
		//	String[] names = {"taro", "jiro", "saburo", "shiro"};
		//	String[] mails = {"taro@mail", "jiro@mail", "saburo@mail", "shiro@mail"};
		//	
		//		@RequestMapping("/{id}")
		//		public DataObject index(@PathVariable int id) {
		//			return new DataObject(id, names[id], mails[id]);
		//		}

//}

////for 3
//class DataObject {
//	private int id;
//	private String name;
//	private String value;
//	public DataObject(int id, String name, String value) {
//		super();
//		this.id = id;
//		this.name = name;
//		this.value = value;
//	}
//
//	public int getId() {
//		return id;
//	}
//	public void setId(int id) {
//		this.id = id;
//	}
//	public String getName() {
//		return name;
//	}
//	public void setName(String name) {
//		this.name = name;
//	}
//	public String getValue() {
//		return value;
//	}
//	public void setValue(String value) {
//		this.value = value;
//	}
//}



//@Controller
//public class HeloController {
//for 1
		//		@RequestMapping("/")
		//		public String index() {
		//			return "index";
		//		}
//for 2 use ModelAndView
		//@RequestMapping("/{num}")
		//	public ModelAndView index(@PathVariable int num, ModelAndView mav) {
		//		int res = 0;
		//		for(int i = 1; i<=num;i++) {
		//			res += i;
		//		}
		//		mav.addObject("msg", "total: " + res);
		//		mav.setViewName("index");
		//		return mav;
		//	}
		//}
//for 3 use EchoServlet(Form&Return)
		// 記述途中
		//	@RequestMapping("/{num}")
		//	public ModelAndView index(@PathVariable int num, ModelAndView mav) {
		//		int res = 0;
		//		for(int i = 1; i<=num;i++) {
		//			res += i;
		//		}
		//		mav.addObject("msg", "total: " + res);
		//		mav.setViewName("index");
		//		return mav;
		//	}
//}

		//@Controller
		//public class HeloController {
		//	@Autowired
		//	MyDataRepository repositrory;
		//	@RequestMapping("/")
		//		public ModelAndView index(ModelAndView mav) {
		//			mav.setViewName("index");
		//			mav.addObject("msg", "this is sample content.");
		//			Iterable<MyData> list = repositrory.findAll();
		//			mav.addObject("data", list);
		//			return mav;
		//		}
		//}

@Controller
public class HeloController {
	
		//	@Autowired
		//	MyDataRepository repository;
		//	
		//	@RequestMapping("/")
		//	public ModelAndView index(ModelAndView mav) {
		//		mav.setViewName("index");
		//		mav.addObject("msg","this is sample content.");
		//		Iterable<MyData> list = repository.findAll();
		//		mav.addObject("datalist",list);
		//		return mav;
		//	}
		//
		//	@RequestMapping(value = "/", method = RequestMethod.POST)
		//	public ModelAndView form(
		//			@ModelAttribute("formModel") MyData mydata, 
		//			ModelAndView mav) {
		//		repository.saveAndFlush(mydata);
		//		return new ModelAndView("redirect:/");
		//	}
			
		// P234 send data by form
		//	@Autowired
		//	MyDataRepository repository;
		//	
		//	@RequestMapping(value = "/", method = RequestMethod.GET)
		//	public ModelAndView index(@ModelAttribute("formModel") MyData mydata, ModelAndView mav) {
		//		mav.setViewName("index");
		//		mav.addObject("msg","this is sample content.");
		//		Iterable<MyData> list = repository.findAll();
		//		mav.addObject("datalist",list);
		//		return mav;
		//	}
		//
		//	@RequestMapping(value = "/", method = RequestMethod.POST)
		//	public ModelAndView form(
		//			@ModelAttribute("formModel") MyData mydata, 
		//			ModelAndView mav) {
		//		repository.saveAndFlush(mydata);
		//		return new ModelAndView("redirect:/");
		//	}
	
		// P234 edit data by form	
		//	@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
		//	public ModelAndView edit(
		//			@ModelAttribute MyData mydata,
		//			@PathVariable int id,
		//			ModelAndView mav) {
		//		mav.setViewName("edit");
		//		mav.addObject("title","this is edit page.");
		//		Optional<MyData> data = repository.findById((long)id);
		//		mav.addObject("formModel",data.get());
		//		return mav;
		//	}
		//	
		//	@RequestMapping(value = "/edit", method = RequestMethod.POST)
		//	public ModelAndView update(
		//			@ModelAttribute MyData mydata,
		//			ModelAndView mav) {
		//		repository.saveAndFlush(mydata);
		//		return new ModelAndView("redirect:/");
		//	}
	
	
	@Autowired
	MyDataRepository repository;
	
	@PersistenceContext
	EntityManager entityManager; //●
	
	MyDataDaolmpl dao; //●
	
//	@PostConstruct
//	public void init(){
//		dao = new MyDataDaolmpl(entityManager); //●
//		MyData d1 = new MyData();
//		d1.setName("tuyano");
//		d1.setMail("syoda@tuyano.com");
//		d1.setMemo("090999999");
//		repository.saveAndFlush(d1);
//		MyData d2 = new MyData();
//		d2.setName("hanako");
//		d2.setMail("hanako@flower");
//		d2.setMemo("080888888");
//		repository.saveAndFlush(d2);
//		MyData d3 = new MyData();
//		d3.setName("sachiko");
//		d3.setMail("sachico@happy");
//		d3.setMemo("070777777");
//		repository.saveAndFlush(d3);
//	}

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("msg","MyDataのサンプルです。");
		dao = new MyDataDaolmpl(entityManager);
		Iterable<MyData> list = dao.getAll(); //●
		mav.addObject("datalist", list);
		return mav;
	}
}


*******************************************************************

package com.tuyano.springboot;

import java.io.Serializable;
import java.util.List;
import com.tuyano.springboot.MyData;

public interface MyDataDao <T> extends Serializable{
	public List<T> getAll();
}

*******************************************************************************************************

package com.tuyano.springboot;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Repository;

@Repository
public class MyDataDaolmpl implements MyDataDao<MyData> {
	private static final long serialVersionUID = 1L;
	
	private EntityManager entityManager;
	
	//Constructor
	public MyDataDaolmpl() {
		super();
	}
	
	public MyDataDaolmpl(EntityManager manager) {
		this();
		entityManager = manager;
	}
//use JPQLver p290 	
//			@Override
//			public List<MyData> getAll() {
//				Query query = entityManager.createQuery("from MyData");
//				@SuppressWarnings("unchecked")
//				List<MyData> list = query.getResultList();
//				entityManager.close();
//				return list;
//			}
//use CriteriaAPIver p318
	@Override
	public List<MyData> getAll() {
		List<MyData> list = null;
		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
//		query.select(root);
//sorting
		query.select(root).orderBy(builder.desc(root.get("id")));
		list = (List<MyData>)entityManager.createQuery(query).getResultList();
		return list;
	}
}

*******************************************************************************************************************************************************

package com.tuyano.springboot;

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

@Entity
@Table(name="goods")
public class MyData {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
//	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	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;
	}
}