orderByによるエンティティのソート
getAll() メソッドの中でorderByを指定して、名前で昇順または降順でソートしてみる。
MyDataDaoCriteria.java の getAll() を変更する。
public List<MyData> getAll() { EntityManager manager = factory.createEntityManager(); List<MyData> list = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<MyData> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); q.select(root).orderBy(builder.desc(root.get("name"))); list = (List<MyData>)manager.createQuery(q).getResultList(); return list; }
取得位置と取得個数の指定も可能。
public List<MyData> getAll() { EntityManager manager = factory.createEntityManager(); List<MyData> list = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<MyData> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); q.select(root).orderBy(builder.desc(root.get("name"))); list = (List<MyData>)manager.createQuery(q) .setFirstResult(2) .setMaxResults(2) .getResultList(); return list; }
JPQLではID・名前・メールアドレスから検索できていたので、CriteriaAPIでも同様に検索できるようにする。
find() メソッドを変更する。
public List<MyData> find(String fstr) { EntityManager manager = factory.createEntityManager(); List<MyData> list = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<MyData> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); int fid = 0; try { fid = Integer.parseInt(fstr); } catch (NumberFormatException e) {} q.select(root).where( builder.or( builder.equal(root.get("id"), fid), builder.like(root.<String>get("name"), "%" + fstr + "%"), builder.like(root.<String>get("mail"), "%" + fstr + "%") ) ); list = (List<MyData>)manager.createQuery(q).getResultList(); return list; }
クリックしたら名前の昇順または降順でソートできるようにする。
まずはJSPにクリックするための矢印を追加する。
<hr> <c:if test="${datalist != null}"> <table> <tr> <th>ID</th> <th>名前<a href="?sort=a">↓</a> <a href="?sort=d">↑</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>
コントローラで引数を受け取れるようにする。
引数なしでも受け付けるようにするために @RequestParam の引数に required = false を追加する。
@RequestMapping(value = "/mydata", method = RequestMethod.GET) public String mydata(@RequestParam(value = "sort", required = false) String s, Model model) { model.addAttribute("title"); model.addAttribute("message", "MyDataのサンプルです。" + s); MyData mydata = new MyData(); model.addAttribute("myData", mydata);
MyDataDao にソート指定できる getAll() を追加し、ソート順を指定するための定数を追加する。
package jp.abc; import java.io.Serializable; import java.util.List; public interface MyDataDao<T> extends Serializable { public static final int ASC = 1; public static final int DESC = 2; public List<T> getAll(); public List<T> getAll(int sort); 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); public List<T> find(String param); }
MyDataDaoImple と MyDataDaoCriteria に、引数付 getAll() を作成する。
引数なしのgetAll() をコピーして貼り付けし、getAll(int sort) に変更すればよい。
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> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); q.select(root); list = (List<MyData>)manager.createQuery(q).getResultList(); return list; } public List<MyData> getAll(int sort) { EntityManager manager = factory.createEntityManager(); List<MyData> list = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<MyData> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); q.select(root); list = (List<MyData>)manager.createQuery(q).getResultList(); return list; }
getAll(int)の実装を修正して、ソートできるようにする。
public List<MyData> getAll(int sort) { EntityManager manager = factory.createEntityManager(); List<MyData> list = null; CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<MyData> q = builder.createQuery(MyData.class); Root<MyData> root = q.from(MyData.class); if (sort == ASC) { q.select(root).orderBy(builder.asc(root.get("name"))); } else { q.select(root).orderBy(builder.desc(root.get("name"))); } list = (List<MyData>)manager.createQuery(q).getResultList(); return list; }
コントローラでは、sortパラメータなしのときは引数なしのgetAll()を、sortパラメータがあるときは、引数ありのgetAll(int)を呼ぶように変更する。
@RequestMapping(value = "/mydata", method = RequestMethod.GET) public String mydata(@RequestParam(value = "sort", required = false) String s, Model model) { model.addAttribute("title"); 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 { int v = s.equals("a") ? MyDataDao.ASC : MyDataDao.DESC; list = dao.getAll(v); } model.addAttribute("datalist", list); return "mydata"; }