2019.04.10
今回もWEBアプリ作成の続きをしていこうと思います。
前回は登録されたデータを全件取得、表示するところまで実装しました。
その続きで今回はいよいよ検索フォームに入力された条件に合致するデータのみ表示するような動作を目指します。
まずコントローラーなどを編集する前にエンティティのフィールドを少し変更したいので以下のように追加、修正しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column private long id; //ISBN番号 @Column(length= 40, nullable = false) private String isbn; //ジャンル @Column(length=20, nullable=false) private String genre; //著者 @Column(length=20, nullable=false) private String author; //タイトル @Column(length=20, nullable=false) private String title; //在庫 @Column @Min(value=0) private int stock; //出版社 @Column(length=50, nullable=true) private String publisher; //発行年 @Column(nullable = true) private int publicationYear; //在庫 @Column(nullable = true) private int unitPrice; |
・インターフェースの定義
ここでは検索ロジックを実装するためにまずはそのインターフェースを定義します。
1 2 3 4 5 6 7 8 | package com.transonic.springboot; import java.io.Serializable; import java.util.List; public interface BookDataDao extends Serializable { public List search(String isbn, String genre, String author, String title); } |
検索をしたいのでメソッド名をsearchとし、必要な引数を設定しました。
・実装
いよいよ検索ロジックの実装をしていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | package com.transonic.springboot; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.Query; import org.springframework.stereotype.Repository; @Repository public class BookDataDaoImpl implements BookDataDao { private EntityManager entityManager; public BookDataDaoImpl() { super(); } public BookDataDaoImpl(EntityManager manager) { this(); entityManager = manager; } @Override public List search (String isbn, String genre, String author, String title){ StringBuilder sql = new StringBuilder(); sql.append("SELECT b From BookData b WHERE "); boolean isbnFlg = false; boolean genreFlg = false; boolean authorFlg = false; boolean titleFlg = false; boolean statusFlg = false; boolean andFlg = false; if(!"".equals(isbn)) { sql.append("b.isbn LIKE :isbn"); isbnFlg = true; andFlg = true; } if(!"".equals(genre)) { if (andFlg) sql.append(" AND "); sql.append("b.genre LIKE :genre"); genreFlg = true; andFlg = true; } if(!"".equals(author)) { if (andFlg) sql.append(" AND "); sql.append("b.author LIKE :author"); authorFlg = true; andFlg = true; } if(!"".equals(title)) { if (andFlg) sql.append(" AND "); sql.append("b.title LIKE :title"); titleFlg = true; andFlg = true; } Query query = entityManager.createQuery(sql.toString()); if (isbnFlg) query.setParameter("isbn", "%" + isbn + "%"); if (genreFlg) query.setParameter("genre", "%" + genre + "%"); if (authorFlg) query.setParameter("author", "%" + author + "%"); if (titleFlg) query.setParameter("title", "%" + title + "%"); return query.getResultList(); } } |
ここで重要なのは22行目からのsearchメソッドです。 ここでやりたいことは検索に必要なクエリを完成させ、それの問い合わせにより得た結果を返すことです。 検索フォームにはユーザーによって入力されないフィールドもあると思います。なのでそれぞれの引数に値が入力されているのかを確認しています。 値が入力されていれば、条件の一部としてクエリに条件を付け足していきます。 また、値が入力されている引数が複数あるようであればクエリに「AND」を付け足すようにしています。
例として、authorに「村上春樹」、titleに「ノルウェイの森」と入力されており、それ以外は入力されなかった場合、ここで完成するクエリ文は以下のようになります。
1 | SELECT b From BookData b WHERE b.author LIKE :author AND b.title LIKE :title |
このクエリにsetParameterで値を割り当てています。
それでは、実装したDAOクラスを使い検索フォームに入力された値に合致するデータを取得するようコントローラーを編集します。 なお、前回と同じように@PostConstructを使いいくつかダミーデータをエンティティオブジェクトとしてクラス内で登録していますが、ここでは省略します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package com.transonic.springboot; import com.shohei.springboot.repositories.BookDataRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; 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.servlet.ModelAndView; import javax.annotation.PostConstruct; import javax.persistence.PersistenceContext; import javax.persistence.EntityManager; @Controller public class StockController { @Autowired BookDataRepository repository; @PersistenceContext EntityManager entityManager; BookDataDaoImpl dao; @RequestMapping(value="/", method = RequestMethod.GET) public ModelAndView index(@ModelAttribute("formModel") BookData bdata, ModelAndView mav) { mav.setViewName("index"); Iterable list = repositoy.findAll(); mav.addObject("booklist",list); return mav; } @RequestMapping(value="/", method = RequestMethod.POST) @Transactional(readOnly=false) public ModelAndView form(@ModelAttribute BookData bdata, ModelAndView mav) { mav.setViewName("index"); if ("".equals(bdata.getIsbn()) && "".equals(bdata.getGenre()) && "".equals(bdata.getAuthor()) && "".equals(bdata.getTitle()) ) { return new ModelAndView("redirect:/"); } else { Iterable result = dao.search(bdata.getIsbn(), bdata.getGenre(), bdata.getAuthor(), bdata.getTitle()); } mav.addObject("formModel",bdata); mav.addObject("booklist",result); return mav; } } |
GETリクエストの際に実行されるメソッドは前回と変わりありません。
POSTリクエストの際には主に先ほど実装したsearchメソッドを呼び出し、返ってきた結果をModelAndViewオブジェクトに登録する流れとなっていますが、フォームのどのボックスにも値が入力されない場合はリダイレクトするようにしてあります。
1 |
ISBN番号 | タイトル | 著者名 | 在庫数 | ジャンル |
---|---|---|---|---|
1 |
今回は少し見た目も変更してみました。 以上でビルドし、アクセスすると以下のような画面が表示されます。 登録されているデータは増えていますがそれ以外は前回と同じですね。 それでは検索してみましょう。
検索内容に合致したデータが表示されました。 次回は、この表示されたデータから本の詳細画面を表示するようなものを実装していきたいと思います。