9月9日

ItemとPurchaseを関連付ける

Item.java

package jp.abc;

import java.util.List;

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.validation.constraints.Min;

import org.hibernate.validator.constraints.NotEmpty;

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

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

	@Column
	@Min(0)
	private int price;

	@Column(nullable = true)
	private String desc;

	@OneToMany(cascade = CascadeType.MERGE)
	private List<Purchase> purchases;

	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 int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
	public List<Purchase> getPurchases() {
		return purchases;
	}
	public void setPurchases(List<Purchase> purchases) {
		this.purchases = purchases;
	}
}

Purchase.java

package jp.abc;

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

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

	@ManyToOne
	private Item item;

	public long getId() {
		return id;
	}

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

	public Item getItem() {
		return item;
	}

	public void setItem(Item item) {
		this.item = item;
	}
}

KartDaoImpl.java

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class KartDaoImpl implements KartDao<Kart> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

	public List<Kart> getAll() {
		return null;
	}

	public Kart findById(long id) {
		EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Kart> query = builder.createQuery(Kart.class);
		Root<Kart> root = query.from(Kart.class);
		query.select(root).where(builder.equal(root.get("id"), id));
		Kart kart = manager.createQuery(query).getSingleResult();
		manager.close();
		return kart;
	}

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

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

Purchase を DB に保存するために、DAO を作成する。

PurchaseDao.java

package jp.abc;

import java.io.Serializable;

public interface PurchaseDao <T> extends Serializable {
	public void add(T o);
}

DAO の実装を作成する。

PurchaseDaoImpl.java

package jp.abc;

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

public class PurchaseDaoImpl implements PurchaseDao<Purchase> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

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

}

ItemContoller.java

package jp.abc;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

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

@Controller
public class ItemController {

	@RequestMapping(value = "/items", method = RequestMethod.GET)
	public String items(Model model) {
		Item item = new Item();
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MyShopのサンプル");
		ItemDao<Item> dao = new ItemDaoImpl();
		List<Item> list = dao.getAll();
		model.addAttribute("item", item);
		model.addAttribute("datalist", list);
		return "items";
	}

	@RequestMapping(value = "items", method = RequestMethod.POST)
	public String form(@Valid @ModelAttribute Item item, Errors result, Model model) {
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample [ERROR]");
			model.addAttribute("message", "値を再チェックしてください");
			return "items";
		}
		ItemDao<Item> dao = new ItemDaoImpl();
		dao.add(item);
		return "redirect:/items";
	}

	@RequestMapping(value = "/update", method = RequestMethod.GET)
	public String edit(@RequestParam(value = "id")int id, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "更新のページ");
		ItemDao<Item> dao = new ItemDaoImpl();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", dao.getAll());
		return "items";
	}

	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public String update(@RequestParam(value = "id")int id,
			@Valid @ModelAttribute Item item,
			Errors result, Model model) {
		ItemDao<Item> dao = new ItemDaoImpl();
		dao.update(item);
		return "redirect:/items";
	}

	@RequestMapping(value = "/delete", method = RequestMethod.GET)
	public String delete(@RequestParam(value = "id")int id, Model model) {
		ItemDao<Item> dao = new ItemDaoImpl();
		dao.delete(id);
		return "redirect:/items";
	}

	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Model model) {
		model.addAttribute("title", "ホーム");
		model.addAttribute("message", "商品");
		ItemDao<Item> dao = new ItemDaoImpl();
		List<Item> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "home";
	}

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String kart(@RequestParam(value = "id")int id, Model model) {
		model.addAttribute("title", "ホーム");
		model.addAttribute("message", "商品");
		ItemDao<Item> dao = new ItemDaoImpl();
		KartDao<Kart> kdao = new KartDaoImpl();
		List<Item> list = dao.getAll();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", list);
		Kart kart = new Kart();
		List<Purchase> plist = kart.getPurchases();
		if (plist == null) plist = new ArrayList<Purchase>();
		Purchase p = new Purchase();
		p.setItem(item);
		plist.add(p);
		kart.setPurchases(plist);
		kdao.add(kart);
		model.addAttribute("kart", kart);
		return "/home";
	}
}

ItemControllerでPurchaseをDBに格納する処理を追加する。

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String kart(@RequestParam(value = "id")int id, Model model) {
		model.addAttribute("title", "ホーム");
		model.addAttribute("message", "商品");
		ItemDao<Item> dao = new ItemDaoImpl();
		KartDao<Kart> kdao = new KartDaoImpl();
		PurchaseDao<Purchase> pdao = new PurchaseDaoImpl();
		List<Item> list = dao.getAll();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", list);
		Kart kart = new Kart();
		List<Purchase> plist = kart.getPurchases();
		if (plist == null) plist = new ArrayList<Purchase>();
		Purchase p = new Purchase();
		p.setItem(item);
		pdao.add(p);
		plist.add(p);
		kart.setPurchases(plist);
		kdao.add(kart);
		model.addAttribute("kart", kart);
		return "/home";
	}

Purchaseを格納する処理を追加して実行すると、JSPのエラーが発生する。
${kart.items} でエラーとなっているので、Kart – Purchase – Item の関連に書き換える。

		<c:if test="${kart != null}">
			カートID: ${kart.id}
			<table>
				<tr><th>商品名</th><th>価格</th></tr>
				<c:forEach var="obj" items="${kart.purchases}" varStatus="status">
					<tr><td>${obj.item.name}</td><td>${obj.item.price}</td></tr>
				</c:forEach>
			</table>
		</c:if>
	</body>

「org.hibernate.LazyInitializationException: could not initialize proxy – no Session」が発生する。
Kartを取得したときに、同時にKartのPurchaseのリストも取得するように@OneToManyアノテーションにfetch引数を追加する。

Kart.java

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

	@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
	@Column(nullable = true)
	private List<Purchase> purchases;

サーバー側でカートを取得できるように、カートのIDをhidden属性でフォームに追加する。

		<table border="1">
		<tr>
			<th class="id">ID</th>
			<th class="name">商品名</th>
			<th class="price">価格</th>
			<th class="desc">説明</th>
			<th >&nbsp;</th>
		</tr>
		<c:if test="${datalist != null}">
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<form:form modelAttribute="item">
					<input type="hidden" name="id" value="${obj.id}" />
					<c:if test="${kart != null}">
						<input type="hidden" name="kid" value="${kart.id}" />
					</c:if>
					<form:errors path="*" element="div" />
					<tr>
						<td><c:out value="${obj.id}" /></td>
						<td><c:out value="${obj.name}" /></td>
						<td class="price"><c:out value="${obj.price}" /></td>
						<td><c:out value="${obj.desc}" /></td>
						<td><input type="submit" value="カートに入れる" /></td>
					</tr>
				</form:form>
			</c:forEach>
		</c:if>
		</table>

サーバー側でカートのIDをリクエストパラメータの引数で取得する。
カートIDは存在しない場合もあるので、required = false にする。
その場合は、プリミティブ型ではなく、Long型のオブジェクトで受け取る。(存在しない場合はnull)
カートIDがある場合は KartDao でクエリを実行して取得する。

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String kart(@RequestParam(value = "id")int id,
					   @RequestParam(value = "kid", required = false)Long kid, Model model) {
		model.addAttribute("title", "ホーム");
		model.addAttribute("message", "商品");
		ItemDao<Item> dao = new ItemDaoImpl();
		KartDao<Kart> kdao = new KartDaoImpl();
		PurchaseDao<Purchase> pdao = new PurchaseDaoImpl();
		List<Item> list = dao.getAll();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", list);
		Kart kart;
		if (kid == null) {
			kart = new Kart();
		} else {
			kart = kdao.findById(kid);
		}
		List<Purchase> plist = kart.getPurchases();
		if (plist == null) plist = new ArrayList<Purchase>();
		Purchase p = new Purchase();
		p.setItem(item);
		pdao.add(p);
		plist.add(p);
		kart.setPurchases(plist);
		kdao.add(kart);
		model.addAttribute("kart", kart);
		return "/home";
	}

この状態で実行すると、2個目の商品を追加したときに「javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist」が発生する。

2回目はカートが存在しているので、add() ではなく update() する。

	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String kart(@RequestParam(value = "id")int id,
					   @RequestParam(value = "kid", required = false)Long kid, Model model) {
		model.addAttribute("title", "ホーム");
		model.addAttribute("message", "商品");
		ItemDao<Item> dao = new ItemDaoImpl();
		KartDao<Kart> kdao = new KartDaoImpl();
		PurchaseDao<Purchase> pdao = new PurchaseDaoImpl();
		List<Item> list = dao.getAll();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", list);
		Kart kart;
		if (kid == null) {
			kart = new Kart();
		} else {
			kart = kdao.findById(kid);
		}
		List<Purchase> plist = kart.getPurchases();
		if (plist == null) plist = new ArrayList<Purchase>();
		Purchase p = new Purchase();
		p.setItem(item);
		pdao.add(p);
		plist.add(p);
		kart.setPurchases(plist);
		if (kid == null) {
			kdao.add(kart);
		} else {
			kdao.update(kart);
		}
		model.addAttribute("kart", kart);
		return "/home";
	}

8月29日

MyShopの実装続き

ItemDaoImple.java は、MyDataDaoCriteria.java を参考に実装する。
MyData を Item に置換すれば動作する。

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class ItemDaoImpl implements ItemDao<Item> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

	public List<Item> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<Item> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Item> query = builder.createQuery(Item.class);
		Root<Item> root = query.from(Item.class);
		query.select(root);
		list = manager.createQuery(query).getResultList();
		manager.close();
		return list;
	}

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

	public Item findById(long id) {
		EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Item> query = builder.createQuery(Item.class);
		Root<Item> root = query.from(Item.class);
		query.select(root).where(builder.equal(root.get("id"), id));
		Item item = manager.createQuery(query).getSingleResult();
		manager.close();
		return item;
	}

	public List<Item> findByName(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<Item> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Item> query = builder.createQuery(Item.class);
		Root<Item> root = query.from(Item.class);
		query.select(root).where(builder.equal(root.get("name"), fstr));
		list = manager.createQuery(query).getResultList();
		manager.close();
		return list;
	}

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

	public void delete(Item o) {
		EntityManager manager = factory.createEntityManager();
		EntityTransaction tx = manager.getTransaction();
		tx.begin();
		Item entity = manager.merge(o);
		manager.remove(entity);
		tx.commit();
		manager.close();
	}

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

}

コントローラでは、update と delete に対応するメソッドを用意する。

ItemController.java

	@RequestMapping(value = "/update", method = RequestMethod.GET)
	public String edit(@RequestParam(value = "id")int id, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "更新のページ");
		ItemDao<Item> dao = new ItemDaoImpl();
		Item item = dao.findById(id);
		model.addAttribute("item", item);
		model.addAttribute("datalist", dao.getAll());
		return "items";
	}

	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public String update(@RequestParam(value = "id")int id,
			@Valid @ModelAttribute Item item,
			Errors result, Model model) {
		ItemDao<Item> dao = new ItemDaoImpl();
		dao.update(item);
		return "redirect:/items";
	}

	@RequestMapping(value = "/delete", method = RequestMethod.GET)
	public String delete(@RequestParam(value = "id")int id, Model model) {
		ItemDao<Item> dao = new ItemDaoImpl();
		dao.delete(id);
		return "redirect:/items";
	}

JSPには、更新と削除が簡単にできるように、アンカーを追加する。
各アンカーのURLで、idに対応するリクエストパラメータを含めておけば、アンカーをクリックするだけで更新と削除が可能になる。

		<c:if test="${datalist != null}">
		<table border="1">
			<tr>
				<th>ID</th>
				<th>商品名<a href="?s=d">↓</a>
				<a href="?s=a">↑</a></th>
			</tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td><c:out value="${obj.id}" /></td>
					<td><c:out value="${obj.name}" /></td>
					<td><a href="update?id=<c:out value="${obj.id}" />">更新</a></td>
					<td><a href="delete?id=<c:out value="${obj.id}" />">削除</a></td>
				</tr>
			</c:forEach>

商品のリストが表示されない場合は、以下の箇所を確認する。

<hr /> タグが水平線で、その下に商品のリストが表示されるが、水平線以下に商品のリストが表示されない場合、datalist が渡されていない可能性がある。

以下の c:if タグで datalist が null でない場合だけ商品のリストを表示している。

		<c:if test="${datalist != null}">

ItemController に、model.addAttribute(“datalist”, list) のコードがあるかどうかを確認すること。

削除前に確認のダイアログを表示するには
head 要素の中に、JavaScript で function を定義する。

		<script type="text/javascript"><!--
		function deleteconfirm(id) {
			if(window.confirm("削除してもいいですか?")) {
				location.href = "delete?id=" + id;
			}
		}
		--></script>

削除のアンカー部分を以下のように修正する。

	<a href="javascript:void(0)" onclick="deleteconfirm(${obj.id})">削除</a>

ユーザー向けフロントページの作成

サイトにアクセスしたユーザーが商品の一覧を参照できるページを作成する。
URLは、 /MyShop/home とする。

商品名 価格 説明  
プレミアムモルツ 220 超クリーミー カートに入れる
エビス 210 おすすめ! カートに入れる
一番搾り 200 さらにおいしくなりました。 カートに入れる

CSSファイルを作成する
src/main/webapp フォルダに css フォルダを新規作成する。
作成した css フォルダ内に home.css を作成する。

CSSファイルを読み込めるようにする
mvc-config.xml ファイルに、CSSフォルダを参照できる設定を追加する。

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

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

    <mvc:annotation-driven />
	<mvc:resources mapping="/css/**" location="/css/" />

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

</beans>

8月26日

HSQLDBを動かす

HSQLDBの設定に、MyShop用データベースインスタンスを追加する。

C:\pleiades45\hsqldb-2.3.4\hsqldb\lib\server.properties を編集する。

server.database.0=file:db/mydatabase
server.dbname.0=mydatabase
server.database.1=file:db/myshop
server.dbname.1=myshop

デスクトップに hsqldb.bat を作成する。

cd C:\pleiades45\hsqldb-2.3.4\hsqldb\lib
java -cp hsqldb.jar org.hsqldb.Server

hsqldb.bat をダブルクリックして、HSQLDBを起動する。

Tomcat8サーバーも再起動すると、データベース接続エラーが出なくなる。

ItemDaoImple.java の実装を行う。

SpringMyApp の、MyDataDaoCriteria.java の内容をコピーして MyData を Item に修正する。

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class ItemDaoImpl implements ItemDao<Item> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

	public List<Item> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<Item> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Item> query = builder.createQuery(Item.class);
		Root<Item> root = query.from(Item.class);
		query.select(root);
		list = manager.createQuery(query).getResultList();
		manager.close();
		return list;
	}

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

}

CRUDを実装する

現状では、全Itemの取得と追加しかできてない。
更新や削除、クエリなどを実装しCRUDを充実させる。

まずは ItemDao.java にメソッドを追加で定義する。

package jp.abc;

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

public interface ItemDao <T> extends Serializable{
	public List<T> getAll();
	public T findById(long id);
	public List<T> findByName(String name);
	public void add(T o);
	public void update(T o);
	public void delete(T o);
	public void delete(long id);
}

ItemDao.java にメソッドを追加して保存すると、ItemDaoImple.java がコンパイルエラーになる。
ItemDaoImpl.java のクラス宣言にマウスカーソルを移動させ、「実装されていないメソッドの追加」を選択する。

各メソッドの内容は、MyDataDaoCriteria.java を参考に実装する。

コントローラも、MyDataController.java を参考に、/update と /delete のURLに対応するメソッドを追加する。

items.jsp には、更新と削除が簡単にできるように、テーブルにリンクを追加する。

7月8日

MsgDataDao で、Criteria API での実装を作ってみる。
クラス名は、MsgDataDaoCriteria.javaとする。

MsgDataDaoImplをコピーして、jp.abc パッケージに貼り付ける。
クラス名の入力が求められるので、「MsgDataDaoCriteria」と入力する。

変更する部分は、getAll() メソッドと findById() メソッドの2箇所。

コントローラ側は、以下の部分を変更する。

	@RequestMapping(value = "/msg", method = RequestMethod.GET)
	public String msg(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MsgDataのサンプルです");
		MsgData msgdata = new MsgData();
		model.addAttribute("msgdata", msgdata);
		MsgDataDao dao = new MsgDataDaoCriteria();
		List<MsgData> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "msgdata";
	}

	@RequestMapping(value = "/msg", method = RequestMethod.POST)
	public String msgform(@Valid @ModelAttribute MsgData msgdata,
			Errors result, Model model) {
		System.out.println("msgform: " + msgdata.getMydata());
		model.addAttribute("msgdata", msgdata);
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample [ERROR]");
			model.addAttribute("message", "値を再チェックしてください。");
			return "msgdata";
		}
		MsgDataDao dao = new MsgDataDaoCriteria();
		dao.add(msgdata);
		return "redirect:/msg";
	}

MsgDataDaoCriteria の、getAll() と findById() は以下のとおり。
MyDataDaoCriteriaからコピーして、MyData を MsgData に書き換えるだけ。

	public List<MsgData> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<MsgData> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MsgData> query = builder.createQuery(MsgData.class);
		Root<MsgData> root = query.from(MsgData.class);
		query.select(root);
		list = manager.createQuery(query).getResultList();
		manager.close();
		return list;
	}

	public MsgData findById(long id) {
		EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MsgData> query = builder.createQuery(MsgData.class);
		Root<MsgData> root = query.from(MsgData.class);
		query.select(root).where(builder.equal(root.get("id"), id));
		MsgData msgdata = manager.createQuery(query).getSingleResult();
		manager.close();
		return msgdata;
	}

7月5日

コントローラにメソッドを追加する

前回までに、JSP・Entity・Daoまで作成したので、残りはControllerの実装を追加すること。

MyDataController.javaに以下のメソッドを追加する。

	@RequestMapping(value = "/msg", method = RequestMethod.GET)
	public String msg(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MsgDataのサンプルです");
		MsgData msgdata = new MsgData();
		model.addAttribute("msgdata", msgdata);
		MsgDataDaoImpl dao = new MsgDataDaoImpl();
		List<MsgData> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "msgdata";
	}

	@RequestMapping(value = "/msg", method = RequestMethod.POST)
	public String msgform(@Valid @ModelAttribute MsgData msgdata,
			Errors result, Model model) {
		System.out.println("msgform: " + msgdata.getMydata());
		model.addAttribute("msgdata", msgdata);
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample [ERROR]");
			model.addAttribute("message", "値を再チェックしてください。");
			return "msgdata";
		}
		MsgDataDaoImpl dao = new MsgDataDaoImpl();
		dao.add(msgdata);
		return "redirect:/msg";
	}

プロパティエディタを作成する。
文字列を数値に変換して、そのIDのMyDataを取得する。
MyDataのIDを文字列化する。

MyDataPropertyEditor.java

package jp.abc;

import java.beans.PropertyEditorSupport;

public class MyDataPropertyEditor extends PropertyEditorSupport {
	public String getAsText() {
		MyData value = (MyData)getValue();
		System.out.println("getAsText: " + value);
		if (value == null) {
			return "";
		} else {
			return "" + value.getId();
		}
	}

	public void setAsText(String value) {
		MyDataDaoImpl dao = new MyDataDaoImpl();
		MyData mydata = dao.findById(Long.parseLong(value));
		System.out.println("setAsTest: " + mydata);
		setValue(mydata);
	}
}

作成したプロパティエディタをコントローラで利用できるようにするために、コントローラの先頭に以下のメソッドを追加する。

@Controller
public class MyDataController {
	@InitBinder
	protected void initBinder(HttpServletRequest request,
				ServletRequestDataBinder binder) throws Exception {
		binder.registerCustomEditor(MyData.class, new MyDataPropertyEditor());;
	}

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String helo(@RequestParam(value = "s", required = false)String s, Model model) {

JSPに間違いがあったので修正。

		<c:if test="${datalist != null}">
		<table border="1">
			<tr>
				<th>ID</th>
				<th>名前<a href="?s=d">↓</a>
				<a href="?s=a">↑</a></th>
			</tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td><c:out value="${obj.id}" /></td>
					<td><c:out value="${obj.mydata.name}" /></td>
					<td><c:out value="${obj.title}" /></td>
					<td><c:out value="${obj.message}" /></td>
				</tr>
			</c:forEach>
		</table>
		</c:if>

HSQLDBの設定を変更

起動用のバッチファイルを修正。

cd C:\pleiades45\hsqldb-2.3.4\hsqldb\lib
java -cp hsqldb.jar org.hsqldb.Server

hsqldb/lib フォルダに server.properties ファイルを作成し、以下の内容を記述。

server.database.0=file:db/mydatabase
server.dbname.0=mydatabase

persistence.xml を修正。

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

pom.xml の変更
HSQLDB Server のバージョンが2.3.4なので、pom.xml の hsqldb もバージョンをあわせる。

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.3.4</version>
		</dependency>
		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>jta</artifactId>
			<version>1.1</version>
		</dependency>

pom.xml を変更したので、プロジェクトを右クリックし、[Maven]-[プロジェクトの更新]と、[実行]-[Maven install]を改めて実行しておくこと。

7月1日

orderByによりエンティティのソート
getAll()メソッドで全エンティティを取得する部分で、ソートを追加してみる。

MyDataDaoCriteria.java

	public List<MyData> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.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 = manager.createQuery(query).getResultList();
		return list;
	}

サイトからのリクエストでソートできるようにする。

まずはJSPに「↑」と「↓」ボタンを追加して、UIを用意する。

		<c:if test="${datalist != null}">
		<table border="1">
			<tr>
				<th>ID</th>
				<th>名前<a href="?s=d">↓</a>
				<a href="?s=a">↑</a></th>
			</tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td><c:out value="${obj.id}" /></td>
					<td><c:out value="${obj.name}" /></td>
				</tr>
			</c:forEach>
		</table>
		</c:if>

ブラウザで http://localhost:8080/SpringMyApp/mydata を再読み込みして、名前の右に「↓↑」が追加されていることを確認する。

コントローラ側でパラメータを受け取れるようにする。
受け取ったパラメータを表示してみる。

MyDataController.java

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String helo(@RequestParam(value = "s", required = false)String s, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MyDataのサンプルです。" + s);
		MyData mydata = new MyData();
		model.addAttribute("myData", mydata);
		MyDataDao<MyData> dao = new MyDataDaoCriteria();
		List<MyData> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "mydata";
	}

「↓↑」をクリックすると、「MyDataのサンプルです。」のあとに「a」か「s」が表示されることで、受け取っていることがわかる。

DAOにソート用パラメータを渡せるようにする。
メソッドをひとつ追加する。
※インタフェースを修正するときは、既存メソッドは必ず残すこと!

特定の実装にのみメソッドを追加したい場合は、MyDataSortableDao extends MyDataDao のように、新しくインタフェースを作成し、MyDataDaoCriteria implements MyDataSortableDao とすると、このクラスだけに影響範囲を絞れる。
ここでは、2クラスしかないので、新しいインタフェースは作成しない。

MyDataDao.java

package jp.abc;

import java.util.List;

public interface MyDataDao<T> {
	public List<T> getAll();
	public List<T> getAll(String s);
	public T findById(long id);
	public List<T> findByName(String name);
	public List<T> find(String param);
	public void add(T data);
	public void update(T data);
	public void delete(T data);
	public void delete(long id);
}

MyDataDaoCriteriaとMyDataDaoImpleにgetAll(String s)を追加する。

MyDataDaoCriteria.java

	public List<MyData> getAll(String s) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		if (s.equals("a")) {
			query.select(root).orderBy(builder.asc(root.get("name")));
		} else {
			query.select(root).orderBy(builder.desc(root.get("name")));
		}
		list = manager.createQuery(query).getResultList();
		return list;
	}

今は使ってないので、メソッドのテンプレート生成だけで済ませておく。
MyDataDaoImple.java

	public List<MyData> getAll(String s) {
		return null;
	}

パラメータが指定された場合は、コントローラから引数つきgetAll()を呼び出すようにする。

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String helo(@RequestParam(value = "s", required = false)String s, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MyDataのサンプルです。" + s);
		MyData mydata = new MyData();
		model.addAttribute("myData", mydata);
		MyDataDao<MyData> dao = new MyDataDaoCriteria();
		List<MyData> list = null;
		if (s == null) {
			list = dao.getAll();
		} else {
			list = dao.getAll(s);
		}
		model.addAttribute("datalist", list);
		return "mydata";
	}

エンティティの連携

MsgDataエンティティを追加して、MyDataに対して複数のMsgDataを関連付けられるようにする。

MsgData.java

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.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;
	}
}

MyDataにコードを追加する。

package jp.abc;

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;

@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;

	@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;
	}
}

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

package jp.abc;

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

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

MsgDataDao の実装クラス MsgDataDaoImple を作成する。
内容的には MyDataDaoImple.java と似ているので、メソッドの中身をコピーして必要な箇所だけ修正すると早い。

package jp.abc;

import java.util.List;

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

public class MsgDataDaoImpl implements MsgDataDao<MsgData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

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

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

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

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

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

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

}

JSPを作成。mydata.jsp をコピーして、msgdata.jsp を作成する。
必要な箇所だけ修正する。

<!DOCTYPE html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta charset="utf-8">
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
		<script src="<c:url value="/resources/js/main.js" />"></script>
		<title>${title}</title>
		<style type="text/css">
		h1 {
			font-size: 16pt;
			background-color: #ccccff;
			padding:3px;
		}
		p {
			color: #000066;
		}
		</style>
	</head>
	<body>
		<h1>${title}</h1>
		<h2>${message}</h2>
		<table>
		<form:form modelAttribute="msgdata">
			<form:errors path="*" element="div" />
			<form:hidden path="id" />
			<tr>
				<td><form:label path="title">タイトル</form:label></td>
				<td><form:input path="title" size="20" /></td>
			</tr>
			<tr>
				<td><form:label path="message">メッセージ</form:label></td>
				<td><form:textarea path="message" cols="20" rows="5" /></td>
			</tr>
			<tr>
				<td><form:label path="mydata">MYDATA_ID</form:label></td>
				<td><form:input path="mydata" size="20" /></td>
			</tr>
			<tr><td><input type="submit"></td></tr>
		</form:form>
		</table>
		<hr />
		<c:if test="${datalist != null}">
		<table border="1">
			<tr>
				<th>ID</th>
				<th>名前<a href="?s=d">↓</a>
				<a href="?s=a">↑</a></th>
			</tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td><c:out value="${obj.id}" /></td>
					<td><c:out value="${obj.name}" /></td>
				</tr>
			</c:forEach>
		</table>
		</c:if>
		<div id="footer"></div>
		<input type="button" value="テスト" onclick="testClicked()">
	</body>
</html>

6月28日

HSQLDBの起動を簡単にする
デスクトップ上で右クリックして、[新規作成]-[テキストドキュメント]を選択する。
デスクトップ上に作成されたファイルの名前を「hsqldb.bat」に変更する。
hsqldb.bat を右クリックして[編集]を選択する。
メモ帳が開かれるので、HSQLDBを起動するために入力していたコマンドをそのまま入力する。

cd C:\pleiades45\hsqldb-2.3.4\hsqldb\lib
java -cp hsqldb.jar org.hsqldb.Server -database db/test

以後は、デスクトップ上の「hsqldb.bat」をダブルクリックするだけで起動できる。

CriteriaAPIによるクエリ
JPQLはSQLに似た文字列を使うため、文字列に間違いがあってもコンパイルできるので、実行時にやっとエラーを検出できる。

これに対して、CriteriaAPIは、クエリの条件をメソッドで指定するので、文字列の間違いはコンパイルエラーで検出できるし、コードを書くときに補完も利用できるので、間違いが起こりにくい。

CriteriaAPIによる実装
jp.abc パッケージに新規クラスを作成する。
インタフェースは MyDataDao を指定する。
クラス名は、CriteriaAPIでの実装であることがわかりやすいように、MyDataDaoCriteriaとする。
クラスを生成したら、インタフェースの総称型の部分を MyData に変更する。
次に、クラス名のところに表示されているコンパイルエラーにマウスカーソルを移動し、「実装されていないメソッドの追加」を選択する。

すべてのメソッドのテンプレートが生成されるので、getAll()メソッドだけ、テキストp.313のリスト6-11を記述する。

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

public class MyDataDaoCriteria implements MyDataDao<MyData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

	public List<MyData> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root);
		list = manager.createQuery(query).getResultList();
		return list;
	}

	public MyData findById(long id) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	public List<MyData> findByName(String name) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	public List<MyData> find(String param) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	public void add(MyData data) {
		// TODO 自動生成されたメソッド・スタブ

	}

	public void update(MyData data) {
		// TODO 自動生成されたメソッド・スタブ

	}

	public void delete(MyData data) {
		// TODO 自動生成されたメソッド・スタブ

	}

	public void delete(long id) {
		// TODO 自動生成されたメソッド・スタブ

	}

}

コントローラで新しく作成したCriteriaAPIを使ったクラスを使うように書き換える。

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MyDataのサンプルです。");
		MyData mydata = new MyData();
		model.addAttribute("myData", mydata);
		MyDataDao<MyData> dao = new MyDataDaoCriteria();
		List<MyData> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "mydata";
	}

add()メソッドは、クエリを使わないので、MyDataDaoImplと同じ実装にする。
update()/delete()も同様に、MyDataDaoImpleの実装をコピーする。

find() は、テキストp.314 のリスト6-12のコードを記述する。
内容は、getAll()とほとんど同じで、selectメソッドを呼び出す行だけが異なる。

	public List<MyData> find(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.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 = manager.createQuery(query).getResultList();
		return list;
	}

find()で実装したコードは、名前の一致で判定しているので、findByName()の仕様に合致する。
findByName()の実装も同じものにする。

findById()はnameをidに変更し、結果を単一のオブジェクトを返すようにすればよい。

	public MyData findById(long id) {
		EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.equal(root.get("id"), id));
		MyData mydata = manager.createQuery(query).getSingleResult();
		return mydata;
	}

	public List<MyData> findByName(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.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 = manager.createQuery(query).getResultList();
		return list;
	}

MyDataDaoCriteriaのコードは、現状で以下のとおり。
まだ、findでは、名前の完全一致しか検索できない。

package jp.abc;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;

public class MyDataDaoCriteria implements MyDataDao<MyData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

	public List<MyData> getAll() {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root);
		list = manager.createQuery(query).getResultList();
		return list;
	}

	public MyData findById(long id) {
		EntityManager manager = factory.createEntityManager();
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.equal(root.get("id"), id));
		MyData mydata = manager.createQuery(query).getSingleResult();
		return mydata;
	}

	public List<MyData> findByName(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.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 = manager.createQuery(query).getResultList();
		return list;
	}

	public List<MyData> find(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.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 = manager.createQuery(query).getResultList();
		return list;
	}

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

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

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

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

}

名前の部分一致に対応するために、コードを一部修正する。

	public List<MyData> find(String fstr) {
		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.like((Path)root.get("name"), "%" + fstr + "%"));
		list = manager.createQuery(query).getResultList();
		return list;
	}

次に、IDの一致とメールアドレスの部分一致にも対応する。
or()メソッドを使用して、複数条件を記述する。

		EntityManager manager = factory.createEntityManager();
		List<MyData> list = null;
		Long fid = 0l;
		try {
			fid = Long.parseLong(fstr);
		} catch (NumberFormatException e) {}
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.or(
				builder.equal(root.get("id"), fid),
				builder.like((Path)root.get("name"), "%" + fstr + "%"),
				builder.like((Path)root.get("mail"), "%" + fstr + "%")
				));
		list = manager.createQuery(query).getResultList();
		return list;
	}

6月21日

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

MyData.java

package jp.abc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
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;
	}
}

DAOインタフェースの準備

MyDataをデータベースに格納・取り出すためのインタフェースを用意する。
最初は、全データの取り出しと、ひとつのデータの追加をできるように、メソッドを定義する。

MyDataDao.java

package jp.abc;

import java.util.List;

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

Daoの実装として、MyDataDaoImpl.java を作成する。

package jp.abc;

import java.util.List;

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

public class MyDataDaoImpl implements MyDataDao<MyData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

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

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

}
種別 テキスト 変更後
Entityクラス MyData MyData
JSP showMessage.jsp mydata.jsp
コントローラ MyAppController MyDataController
URL /helo /mydata

MyDataController.java

package jp.abc;

import java.util.List;

import javax.validation.Valid;

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

@Controller
public class MyDataController {

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String helo(Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "MyDataのサンプルです。");
		MyData mydata = new MyData();
		model.addAttribute("myData", mydata);
		MyDataDao<MyData> dao = new MyDataDaoImpl();
		List<MyData> list = dao.getAll();
		model.addAttribute("datalist", list);
		return "mydata";
	}

	@RequestMapping(value = "/mydata", method = RequestMethod.POST)
	public String form(@Valid @ModelAttribute MyData mydata,
			Errors result, Model model) {
		if (result.hasErrors()) {
			model.addAttribute("title", "Sample [ERROR]");
			model.addAttribute("message", "値を再チェックしてください。");
			return "mydata";
		}
		MyDataDao<MyData> dao = new MyDataDaoImpl();
		dao.add(mydata);
		return "redirect:/mydata";
	}

}

mydata.jsp

<!DOCTYPE html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta charset="utf-8">
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
		<script src="<c:url value="/resources/js/main.js" />"></script>
		<title>${title}</title>
		<style type="text/css">
		h1 {
			font-size: 16pt;
			background-color: #ccccff;
			padding:3px;
		}
		p {
			color: #000066;
		}
		</style>
	</head>
	<body>
		<h1>${title}</h1>
		<h2>${message}</h2>
		<table>
		<form:form modelAttribute="myData">
			<form:errors path="*" element="div" />
			<tr>
				<td>
					<form:label path="name">名前</form:label>
				</td>
				<td>
					<form:input path="name" size="20"/>
				</td>
			</tr>
			<tr>
				<td>
					<form:label path="age">年齢</form:label>
				</td>
				<td>
					<form:input path="age" size="20" />
				</td>
			</tr>
			<tr>
				<td>
					<form:label path="mail">メール</form:label>
				</td>
				<td>
					<form:input path="mail" size="20" />
				</td>
			</tr>
			<tr>
				<td>
					<form:label path="memo">メモ</form:label>
				</td>
				<td>
					<form:textarea path="memo" cols="20" rows="5" />
				</td>
			</tr>
			<tr><td><input type="submit"></td></tr>
		</form:form>
		</table>
		<hr />
		<c:if test="${datalist != null}">
		<table border="1">
			<tr><th>ID</th><th>名前</th></tr>
			<c:forEach var="obj" items="${datalist}" varStatus="status">
				<tr>
					<td><c:out value="${obj.id}" /></td>
					<td><c:out value="${obj.name}" /></td>
				</tr>
			</c:forEach>
		</table>
		</c:if>
		<div id="footer"></div>
		<input type="button" value="テスト" onclick="testClicked()">
	</body>
</html>

DAOにCRUDを追加する。

package jp.abc;

import java.util.List;

public interface MyDataDao<T> {
	public List<T> getAll();
	public T findById(long id);
	public List<T> findByName(String name);
	public void add(T data);
	public void update(T data);
	public void delete(T data);
	public void delete(long id);
}

DAOを実装する。

package jp.abc;

import java.util.List;

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

public class MyDataDaoImpl implements MyDataDao<MyData> {
	private static EntityManagerFactory factory =
			Persistence.createEntityManagerFactory("persistenceUnit");

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

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

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

	public List<MyData> findByName(String name) {
		EntityManager manager = factory.createEntityManager();
		return (List<MyData>)manager.createQuery("from MyData where name = " + name).getResultList();
	}

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

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

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

}

6月17日

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

データベースはHSQLDBを使用する。
データベースを利用するためのライブラリを追加するため、pom.xmlに以下の内容を追加する。

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.2.9</version>
		</dependency>
		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>jta</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>3.2.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.2.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.3.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

spring-aspects の箇所でエラーが出た場合は、${spring.version} を ${spring-framework.version} に変更する。それでエラーが消えればOK。

ファイルを保存したら、プロジェクトを右クリックし、[実行]-[Maven install]を実行する。
コンソールに「BUILD SUCCESS」と表示されればOK。

HSQLDBのプラグインがなぜかインストールできないので、HSQLDBをダウンロードして、C:\pleiades45 の下に展開する。

HSQLDBをここからダウンロード

コマンドプロンプトを開き、javaコマンドを実行する。
$ java

コマンドが見つからない場合は、環境変数を追加する。
スタートメニューでコンピュータを右クリックし、「プロパティ」を選択する。
「システム詳細設定」をクリック。
「環境変数」をクリックし、「新規」をクリックし、以下の内容を入力する。

変数名: PATH
変数値: C:\pleiades45\java\8\bin

コマンドプロンプトを再起動して、以下のコマンドを実行する。

$ cd C:\pleiades45\hsqldb-2.3.4\hsqldb\lib
$ java -cp hsqldb.jar org.hsqldb.Server -database db/test

これでHSQLDBサーバーが起動する。

もうひとつコマンドプロンプトを起動して、HSQLDBクライアントを起動する。

$ cd C:\pleiades45\hsqldb-2.3.4\hsqldb\lib
$ java -cp hsqldb.jar org.hsqldb.util.DatabaseManager

database.properties ファイルを作成する
src/main/resources/spring フォルダを右クリックし、「新規」を選択する。
[一般]-[ファイル]を選択し、ファイル名に「database.properties」と入力して完了する。
ファイル内には以下の内容を記述する。

database.driverClassName=org.hsqldb.jdbc.JDBCDriver
database.url=jdbc:hsqldb:hsql://localhost/
database.username=sa
database.password=

persistence.xml を作成する
src/main/resources フォルダを右クリックし、「新規」を選択する。
[一般]-[フォルダ]を選択し、フォルダ名に「META-INF」と入力して完了する。

src/main/resources/META-INF フォルダを右クリックし、「新規」を選択する。
[XML]-[XMLファイル]を選択し、ファイル名に「persistence.xml」と入力して完了する。
persistence.xmlには以下の内容を記述する。

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

application-config.xmlファイルの変更
以下の内容に変更する。

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

エンティティの作成
src/main/java の jp.abc パッケージにクラス「MyData」を新規作成する。

最初にクラス名の前に @Entity と @Table アノテーションを追加し、インスタンス変数を定義する。
インスタンス変数を定義したら、「getter および setter の生成」でgetter/setterを生成する。

MyData.java

package jp.abc;

import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="mydata")
public class MyData {
	private long id;
	private String name;
	private String mail;
	private Integer age;
	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;
	}
}

pom.xml 全体

<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>org.springframework.samples.service.service</groupId>
  <artifactId>SpringMyApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

    <properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Web -->
		<jsp.version>2.2</jsp.version>
		<jstl.version>1.2</jstl.version>
		<servlet.version>2.5</servlet.version>


		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>

	<dependencies>

		<!-- Spring MVC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Other Web dependencies -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>${jsp.version}</version>
			<scope>provided</scope>
		</dependency>

		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>


		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.0.1.Final</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.2.9</version>
		</dependency>
		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>jta</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>3.2.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.2.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.3.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

	</dependencies>
</project>