有時候需要用到動態查詢。動態查詢 Specification 使用需實現接口JpaSpecificationExecutor

1 package com.hik.dao; 2 3 import java.util.List; 4 5 import org.springframework.data.jpa.repository.JpaRepository; 6 import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 7 import org.springframework.data.jpa.repository.Query; 8 9 import com.hik.entity.Book; 10 11 /** 12 * 圖書Dao接口 13 * @author jed 14 * 15 */ 16 public interface BookDao extends JpaRepository<Book, Integer>,JpaSpecificationExecutor<Book> { 17 18 //Hql語句查詢 19 @Query("select b from Book b where b.bookName like %?1%") 20 public List<Book> findByBookName(String bookName); 21 22 //本地sql語句查詢 23 @Query(value="select * from t_book order by RAND() limit ?1",nativeQuery=true) 24 public List<Book> randomList(Integer n); 25 }
JpaSpecificationExecutor接口方法

1 /* 2 * Copyright 2008-2011 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.springframework.data.jpa.repository; 17 18 import java.util.List; 19 20 import org.springframework.data.domain.Page; 21 import org.springframework.data.domain.Pageable; 22 import org.springframework.data.domain.Sort; 23 import org.springframework.data.jpa.domain.Specification; 24 25 /** 26 * Interface to allow execution of {@link Specification}s based on the JPA criteria API. 27 * 28 * @author Oliver Gierke 29 */ 30 public interface JpaSpecificationExecutor<T> { 31 32 /** 33 * Returns a single entity matching the given {@link Specification}. 34 * 35 * @param spec 36 * @return 37 */ 38 T findOne(Specification<T> spec); 39 40 /** 41 * Returns all entities matching the given {@link Specification}. 42 * 43 * @param spec 44 * @return 45 */ 46 List<T> findAll(Specification<T> spec); 47 48 /** 49 * Returns a {@link Page} of entities matching the given {@link Specification}. 50 * 51 * @param spec 52 * @param pageable 53 * @return 54 */ 55 Page<T> findAll(Specification<T> spec, Pageable pageable); 56 57 /** 58 * Returns all entities matching the given {@link Specification} and {@link Sort}. 59 * 60 * @param spec 61 * @param sort 62 * @return 63 */ 64 List<T> findAll(Specification<T> spec, Sort sort); 65 66 /** 67 * Returns the number of instances that the given {@link Specification} will return. 68 * 69 * @param spec the {@link Specification} to count instances for 70 * @return the number of instances 71 */ 72 long count(Specification<T> spec); 73 }
Specification接口

1 /* 2 * Copyright 2008-2017 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.springframework.data.jpa.domain; 17 18 import javax.persistence.criteria.CriteriaBuilder; 19 import javax.persistence.criteria.CriteriaQuery; 20 import javax.persistence.criteria.Predicate; 21 import javax.persistence.criteria.Root; 22 23 /** 24 * Specification in the sense of Domain Driven Design. 25 * 26 * @author Oliver Gierke 27 * @author Thomas Darimont 28 * @author Krzysztof Rzymkowski 29 */ 30 public interface Specification<T> { 31 32 /** 33 * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given 34 * {@link Root} and {@link CriteriaQuery}. 35 * 36 * @param root 37 * @param query 38 * @return a {@link Predicate}, may be {@literal null}. 39 */ 40 Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); 41 }
BookDao接口類:

1 package com.hik.dao; 2 3 import java.util.List; 4 5 import org.springframework.data.jpa.repository.JpaRepository; 6 import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 7 import org.springframework.data.jpa.repository.Query; 8 9 import com.hik.entity.Book; 10 11 /** 12 * 圖書Dao接口 13 * @author jed 14 * 15 */ 16 public interface BookDao extends JpaRepository<Book, Integer>,JpaSpecificationExecutor<Book> { 17 18 //Hql語句查詢 19 @Query("select b from Book b where b.bookName like %?1%") 20 public List<Book> findByBookName(String bookName); 21 22 //本地sql語句查詢 23 @Query(value="select * from t_book order by RAND() limit ?1",nativeQuery=true) 24 public List<Book> randomList(Integer n); 25 }
BookController類

1 package com.hik.Controller; 2 3 import java.util.List; 4 5 import javax.annotation.Resource; 6 import javax.persistence.criteria.CriteriaBuilder; 7 import javax.persistence.criteria.CriteriaQuery; 8 import javax.persistence.criteria.Predicate; 9 import javax.persistence.criteria.Root; 10 11 import org.springframework.data.jpa.domain.Specification; 12 import org.springframework.stereotype.Controller; 13 import org.springframework.web.bind.annotation.GetMapping; 14 import org.springframework.web.bind.annotation.PathVariable; 15 import org.springframework.web.bind.annotation.PostMapping; 16 import org.springframework.web.bind.annotation.RequestMapping; 17 import org.springframework.web.bind.annotation.RequestMethod; 18 import org.springframework.web.bind.annotation.ResponseBody; 19 import org.springframework.web.servlet.ModelAndView; 20 21 import com.hik.dao.BookDao; 22 import com.hik.entity.Book; 23 24 /** 25 * Book控制類 26 * @author jed 27 * 28 */ 29 @Controller 30 @RequestMapping("/book") 31 public class BookController { 32 33 @Resource 34 private BookDao bookDao; 35 36 /** 37 * 查詢所有圖書 38 * @return 39 */ 40 @RequestMapping(value="/list") 41 public ModelAndView list() { 42 ModelAndView mav = new ModelAndView (); 43 mav.addObject("bookList", bookDao.findAll()); 44 mav.setViewName("bookList"); 45 return mav; 46 } 47 48 /** 49 * 根據條件動態查詢 50 * @param book 51 * @return 52 */ 53 @RequestMapping(value="/list2") 54 public ModelAndView list2(Book book) { 55 ModelAndView mav = new ModelAndView(); 56 List<Book> bookList = bookDao.findAll(new Specification<Book>() { 57 58 @Override 59 public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 60 Predicate predicate= cb.conjunction(); 61 if(book!=null) { 62 if(book.getBookName()!=null && !"".equals(book.getBookName())) { 63 predicate.getExpressions().add(cb.like(root.get("bookName"), "%"+book.getBookName()+"%")); 64 } 65 } 66 return predicate; 67 } 68 69 }); 70 mav.addObject("bookList",bookList); 71 mav.setViewName("bookList"); 72 return mav; 73 } 74 75 /** 76 * 添加圖書 77 * @param book 78 * @return 79 */ 80 @RequestMapping(value="/add", method=RequestMethod.POST) 81 public String add(Book book) { 82 bookDao.save(book); 83 return "forward:/book/list"; 84 } 85 86 @GetMapping(value="/preUpdate/{id}") 87 public ModelAndView preUpdate(@PathVariable("id") Integer id) { 88 ModelAndView mav = new ModelAndView(); 89 mav.addObject("book", bookDao.getOne(id)); 90 mav.setViewName("bookUpdate"); 91 return mav; 92 } 93 94 /** 95 * 修改圖書 96 * @param book 97 * @return 98 */ 99 @PostMapping(value="/update") 100 public String update(Book book) { 101 bookDao.save(book); 102 return "forward:/book/list"; 103 } 104 105 /** 106 * 刪除圖書 107 * @param id 108 * @return 109 */ 110 @RequestMapping(value="/delete",method = RequestMethod.GET) 111 public String delete(Integer id) { 112 bookDao.delete(id); 113 return "forward:/book/list"; 114 } 115 116 @ResponseBody 117 @GetMapping(value="/queryByName") 118 public List<Book> queryByName() { 119 return bookDao.findByBookName("思想"); 120 } 121 122 @ResponseBody 123 @GetMapping(value="/randomList") 124 public List<Book> randomList(){ 125 return bookDao.randomList(2); 126 } 127 }
bookList.ftl

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>圖書管理頁面</title> 6 </head> 7 <body> 8 <a href="/bookAdd.html">添加圖書</a></br> 9 <form method="post" action="/book/list2"> 10 圖書名稱:<input type="text" name="bookName" /> 11 <input type="submit" value="搜索"/> 12 </form> 13 <table> 14 <tr> 15 <th>編號</th> 16 <th>圖書名稱</th> 17 <th>操作</th> 18 </tr> 19 <#list bookList as book> 20 <tr> 21 <td>${book.id}</td> 22 <td>${book.bookName}</td> 23 <td> 24 <a href="/book/preUpdate/${book.id}">修改</a> 25 <a href="/book/delete?id=${book.id}">刪除</a> 26 </td> 27 </tr> 28 </#list> 29 </table> 30 </body> 31 </html>
訪問:http://localhost:8888/book/list2
輸入查詢條件,點擊搜索
查詢結果: