7月14日

Criteria APIを使用したクエリ

Webページにページングを追加する

Criteria API での検索には、setFirstResult() で先頭の位置を指定し、setMaxResults()で取得するデータの最大数を指定する。

MyDataDaoImpl.java

	public List<MyData> getList() {
		int offset = 0;
		int limit = 5;
		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)
				.setFirstResult(offset)
				.setMaxResults(limit)
				.getResultList();
		return list;
	}

JSPにページング用のリンクを追加する。

mydata.jsp

	<a href="mydata?offset=0">1</a>&nbsp;<a href="mydata?offset=5">2</a>

コントローラでリクエストパラメータを受け取る。@RequestParam アノテーションを追加し、Integer型のoffsetパラメータを追加する。

MyDataController.java

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

DAOにパラメータつきのgetList()をオーバーロードで追加する。

MyDataDao.java

public interface MyDataDao <T> extends Serializable {
	public List<T> getAll();
	public List<T> getList();
	public List<T> getList(int offset, int max);
	public List<T> find(String param);

DAOの実装にgetList()を追加する。

MyDataDaoImpl.java

	public List<MyData> getList(int offset, int max) {
		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)
				.setFirstResult(offset)
				.setMaxResults(max)
				.getResultList();
		return list;
	}

コントローラでリクエストパラメータから受け取ったオフセットをDAOに渡すようにする。

MyDataController.java

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String mydata(@RequestParam(required = false) Integer offset, Model model) {
		model.addAttribute("title", "Sample " + offset);
		model.addAttribute("message", "MyDataのサンプルです");
		MyData mydata = new MyData();
		model.addAttribute("myData", mydata);
		MyDataDao<MyData> dao = new MyDataDaoImpl();
		int off = offset == null ? 0 : offset;
		List<MyData> list = dao.getList(off, 5);
		model.addAttribute("datalist", list);
		return "mydata";
	}

7月7日

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

Tomcatサーバーを再起動するとデータベースに保存したデータが消えてしまう問題を修正する。

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>

database.properties

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

データを削除するときに例外が発生する問題を修正する。
MyDataDaoImpl.java

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

複数の名前つきパラメータ

入力された文字列を、idだけでなく、名前とメールアドレスからも検索できるようにする。

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 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 MyData findById(long id) {
		EntityManager manager = factory.createEntityManager();
		String sql = "from MyData where id = " + id;
		MyData mydata = (MyData)manager.createQuery(sql).getSingleResult();
		return mydata;
	}

	public MyData findByName(String name) {
		return null;
	}

	public List<MyData> find(String param) {
		EntityManager manager = factory.createEntityManager();
		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(param);
		} catch (NumberFormatException e) {}
		Query query = manager.createQuery(qstr)
					 .setParameter("fid", fid)
					 .setParameter("fname", "%" + param + "%")
					 .setParameter("fmail", "%" + param + "%");
		list = query.getResultList();
		manager.close();
		return list;
	}

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

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

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

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

データベースマネージャからSQLをダイレクトに実行する方法

  1. 以下のファイルをローカルにコピーする。
    \\KGAKUSEI1\share\澤田\hsqldb-2.3.2.zip
  2. C:\Users\se3\db の下に解凍する。
  3. コマンドプロンプトを起動。
  4. 以下のコマンドを実行する
    > cd C:\Users\se3\db\hsqldb-2.3.2\hsqldb
    > java -cp lib/hsqldb.jar org.hsqldb.util.DatabaseManager
    

hsqldb

spring12

hsqldbmanager

「?」による番号指定のパラメータと @NamedQuery による名前付きクエリーはパス(余裕がある人は試してもよい)。

Criteria APIによる検索

MyDataDao.javaにgetList()メソッドを追加。

package jp.abc;

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

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

MyDataDaoImple.java

	public List<MyData> getList() {
		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;
	}

MyDataController.java
mydata()メソッド内の dao.getAll() を dao.getList() に書き換える。

	@RequestMapping(value = "/mydata", method = RequestMethod.GET)
	public String mydata(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.getList();
		model.addAttribute("datalist", list);
		return "mydata";
	}

MyDataDao.java に search()メソッドを追加する。

package jp.abc;

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

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

MyDataDaoImpl.java にも search()メソッドを追加する。

	public List<MyData> search(String param) {
		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"), param));
		list = manager.createQuery(query).getResultList();
		return list;
	}

MyDataController.java で dao.find() を呼び出しているところを search() に書き換える。

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

	@RequestMapping(value = "/find", method = RequestMethod.POST)
	public String search(@RequestParam(value = "fstr") String param, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", "「" + param + "」の検索結果");
		MyDataDao<MyData> dao = new MyDataDaoImpl();
		List<MyData> list = dao.search(param);
		model.addAttribute("datalist", list);
		return "find";
	}

7月3日

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

ファイルに保存するように設定を修正

src/main/resources/spring/database.properties

database.driverClassName=org.hsqldb.jdbc.JDBCDriver
database.url=jdbc:hsqldb:file:../workspace/SpringMyApp/db/mydata
database.username=sa
database.password=

src/main/resources/META-INF/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="create" />
      <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>

IDでの検索機能

find.jsp

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

<html>
<head>
	<meta charset="utf-8">
	<title>${title}</title>
</head>

<body>
	<h1>${title}</h1>
	<p>${message}</p>
	<table>
	<form action="/SpringMyApp/find" method="post">
		<tr>
			<td>FIND:</td>
			<td><input type="text" name="fstr" size="20" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" /></td>
		</tr>
	</form>
	</table>
	<hr>
	<c:if test="${datalist != null}">
	<table border="1">
		<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>
</body>

MyDataController.java

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

	@RequestMapping(value = "/find", method = RequestMethod.POST)
	public String search(@RequestParam(value = "fstr") String param, Model model) {
		model.addAttribute("title", "Sample");
		model.addAttribute("message", param + "の検索結果");
		MyDataDao<MyData> dao = new MyDataDaoImpl();
		List<MyData> list = dao.find(param);
		model.addAttribute("datalist", list);
		return "find";
	}

MyDataDao.java

package jp.abc;

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

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

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 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 MyData findById(long id) {
		EntityManager manager = factory.createEntityManager();
		String sql = "from MyData where id = " + id;
		MyData mydata = (MyData)manager.createQuery(sql).getSingleResult();
		return mydata;
	}

	public MyData findByName(String name) {
		return null;
	}

	public List<MyData> find(String param) {
		EntityManager manager = factory.createEntityManager();
		Query query = manager.createQuery("from MyData where id = " + param);
		List<MyData> list = query.getResultList();
		manager.close();
		return list;
	}

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

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

	public void delete(MyData mydata) {
		EntityManager manager = factory.createEntityManager();
		EntityTransaction transaction = manager.getTransaction();
		transaction.begin();
		manager.remove(mydata);
		transaction.commit();
		manager.close();
	}

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

spring10

インメモリモードやファイルモードがうまく動作しないので、サーバーモードで動作させる。
Eclipseマーケットプレイスから HSQLDB Database Server Plugin をインストールする。

spring11