SpringBoot动态查询 Specification使用
有时候需要用到动态查询。动态查询 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
输入查询条件,点击搜索
查询结果: