9月12日

エンティティの連携

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

Profileクラスの追加

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

Profile.java

package jp.abc;

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

import org.hibernate.validator.constraints.NotEmpty;

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

	@Column
	@NotEmpty
	private String name;

	@OneToOne
	private Result result;

	public long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public Result getResult() {
		return result;
	}

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

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

Result.java

package jp.abc;

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

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

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

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

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

	@OneToOne
	private Profile profile;

	public long getId() {
		return id;
	}

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

	public String getNumber() {
		return number;
	}

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

	public int getScore() {
		return score;
	}

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

	public Profile getProfile() {
		return profile;
	}

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

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

ProfileDao.java

package jp.abc;

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

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

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

ProfileDaoImple.java

package jp.abc;

import java.util.List;

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

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

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

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

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

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

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

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

}

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

profile.jsp

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

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

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

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

</body>
</html>

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

ProfileController.java

package jp.abc;

import java.util.List;

import javax.validation.Valid;

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

@Controller
public class ProfileController {

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

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

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

ResultPropertyEditor.java

package jp.abc;

import java.beans.PropertyEditorSupport;

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

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

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

ProfileController.java

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

exam-6

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

profile.jsp

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

exam-7

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です