試験範囲について
- Eclipseを使った開発
- ストリームを利用したファイル入出力とURLからのデータ取得
- FizzBuzz問題を例題としてTDDによる開発手法の学習
- TDDBC大阪の例題の自動販売機を実装する
- JavaによるWebアプリケーションの基礎(Servlet/JSP/JSTL)
- JSPによる入力フォームとServletでのデータの受け取り
サービスとリポジトリは便利ですが、使わなくてもWebアプリケーションを作れるので、今回はパスします。
興味がある人は自分でやってみてください。
エンティティの連携
MsgDataエンティティを作成する。
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を修正する
MyDataに、MsgDataへの参照を追加する。
インスタンス変数を追加したら、Eclipseの[ソース]-[getterおよびsetterの生成]でアクセサメソッドを自動生成する。
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の用意
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); }
MsgDataDaoImplクラスを作成する。
テキストの通りに各メソッドに @Override アノテーションをつけるとコンパイルエラーになる。
これは、プロジェクトの設定で Javaコンパイラのバージョンが1.5になっているため。
1.6に変更すれば @Override アノテーションのコンパイルエラーは消える。
同時に、プロジェクト・ファセットの設定でバージョンを合わせる必要がある。
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"); @Override public List<MsgData> getAll() { EntityManager manager = factory.createEntityManager(); List<MsgData> list = null; Query q = manager.createQuery("from MsgData"); list = q.getResultList(); manager.close(); return list; } @Override public MsgData findById(long id) { EntityManager manager = factory.createEntityManager(); Query q = manager.createQuery("from MsgData where id = " + id); return (MsgData)q.getSingleResult(); } @Override public void add(MsgData data) { EntityManager manager = factory.createEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); manager.persist(data); tx.commit(); manager.close(); } @Override public void update(MsgData data) { EntityManager manager = factory.createEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); manager.merge(data); tx.commit(); manager.close(); } @Override 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(); } @Override public void delete(long id) { delete(findById(id)); } }
ビューテンプレートの用意
[新規]-[JSPファイル]でJSPファイルを作成する。
ファイル名はテキストの通り「showMsgData.jsp」とする。
<!DOCTYPE html> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${title}</title> <style> h1 { font-size: 16pt; background-color: #ccccff; padding: 3px;} p { color: #000066; } </style> </head> <body> <h1>${title}</h1> <p>${message}</p> <table> <form:form modelAttribute="msgdata"> <tr> <td></td> <td><form:errors path="*" /></td> </tr> <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></td> <td><input type="submit" /></td> </tr> </form:form> </table> <hr /> <c:if test="${datalist != null}"> <table> <tr> <th>ID</th><th>投稿者</th><th>タイトル</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.mydata.name}" /></td> <td><c:out value="${obj.title}" /></td> <td><c:out value="${obj.message}" /></td> </tr> </c:forEach> </table> </c:if> </body> </html>
コントローラに新しいURL用のメソッドを追加する
@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<MsgData> dao = new MsgDataDaoImpl(); List<MsgData> list = dao.getAll(); model.addAttribute("datalist", list); return "showMsgData"; } @RequestMapping(value = "/msg", method = RequestMethod.POST) public String msgform(@Valid @ModelAttribute MsgData msgdata, Errors result, Model model) { System.out.println("msgform: " + msgdata.getMydata()); if (result.hasErrors()) { model.addAttribute("title", "Sample [ERROR]"); model.addAttribute("message", "値を再チェックしてください。"); return "showMsgData"; } MsgDataDao<MsgData> dao = new MsgDataDaoImpl(); dao.add(msgdata); return "redirect:/msg"; }
POSTするとエラーが発生する。
フォームではMYDATA_IDは単なる文字としての値なので、これをMyDataのインスタンスに変換するための処理が必要になる。
そのために、PropertyEditor を継承するクラス MyDataPropertyEditor を用意する。
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) { MyDataDao<MyData> dao = new MyDataDaoImpl(); MyData mydata = (MyData)dao.findById(Long.parseLong(value)); System.out.println("setAsText: " + mydata); setValue(mydata); } }
作成した MyDataPropertyEditor を使用するためのコードをコントローラに追加する。
@Controller public class MyDataConroller { @InitBinder protected void initBinder(HttpServletRequest req, ServletRequestDataBinder binder) throws Exception { binder.registerCustomEditor(MyData.class, new MyDataPropertyEditor()); }