spring boot学习(5) SpringBoot 之Spring Data Jpa 支持(2)
第三节:自定义查询@Query
有时候复杂sql使用hql方式无法查询,这时候使用本地查询,使用原生sql的方式;
第四节:动态查询Specification 使用
什么时候用呢?比如搜索有很多条件,有时候用户只填了一个,有时候填很多,不确定条件的数目,这时候动态判断,拼接sql,使用Specification
下面是例子讲解:
com.cy.dao.BookDao.java:
package com.cy.dao; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import com.cy.entity.Book; public interface BookDao extends JpaRepository<Book, Integer>, JpaSpecificationExecutor<Book>{ // ?1代表第一个参数 // 这种是hql形式 @Query("select b from Book b where b.name like %?1%") public List<Book> findByName(String name); /** * 随机查询n条图书 * nativeQuery默认是hql查询,这里true表示使用本地查询,就是原生的sql方式 * @param n * @return */ @Query(value="select * from t_book order by RAND() limit ?1", nativeQuery=true) public List<Book> randomList(Integer n); }
注意:
上面BookDao继承了JpaSpecificationExecutor,这个接口里面才可以动态条件查询;继承这个是为了动态查询Specification 使用
BookController:
package com.cy.controller; import java.util.List; import javax.annotation.Resource; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.cy.dao.BookDao; import com.cy.entity.Book; @Controller @RequestMapping("/book") public class BookController { @Resource private BookDao bookDao; /** * 根据条件动态查询 */ @RequestMapping("/list2") public ModelAndView list2(Book book){ ModelAndView mav = new ModelAndView(); List<Book> bookList = bookDao.findAll(new Specification<Book>(){ @Override public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate predicate = cb.conjunction(); if(book!=null){ if(book.getName()!=null && !"".equals(book.getName())){ predicate.getExpressions().add(cb.like(root.get("name"), "%"+book.getName()+"%")); } if(book.getAuthor()!=null && !"".equals(book.getAuthor())){ predicate.getExpressions().add(cb.like(root.get("author"), "%"+book.getAuthor()+"%")); } } return predicate; } }); mav.addObject("book", book); mav.addObject("bookList", bookList); mav.setViewName("bookList"); return mav; } /** * 根据名字查找图书 * @return */ @ResponseBody @GetMapping("/queryByName") public List<Book> queryByName(){ return bookDao.findByName("编程"); } //随机查询一条图书 @ResponseBody @GetMapping("/randomList") public List<Book> randomList(){ return bookDao.randomList(1); } }
src/main/resouces/templates/bookList.ftl里面增加两个搜索框:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>图书管理</title> </head> <body> <a href="/bookAdd.html">添加</a>
<!-- 这个book返回来是为了搜素框回显使用的 -->
<form method="post" action="/book/list2"> 图书名称:<input type="text" name="name" value="${book.name}"/> 图书作者:<input type="text" name="author" value="${book.author}" /> <input type="submit" value="搜索"/> </form> <table> <tr> <th>编号</th> <th>图书名称</th> <th>图书作者</th> <th>操作</th> </tr> <#list bookList as book> <tr> <td>${book.id}</td> <td>${book.name}</td> <td>${book.author}</td> <td> <a href="/book/preUpdate/${book.id}">修改</a> <a href="/book/delete?id=${book.id}">删除</a> </td> </tr> </#list> </table> </body> </html>
测试:
数据表情况:
mysql> select * from t_book;
+----+--------+--------------+
| id | author | name |
+----+--------+--------------+
| 2 | 作者1 | 图书五 |
| 7 | 外国佬 | java编程思想 |
| 8 | 王五 | 大刀王五 |
| 9 | 有人 | php编程 |
+----+--------+--------------+
1.http://localhost/book/queryByName显示: [{"id":7,"name":"java编程思想","author":"外国佬"},{"id":9,"name":"php编程","author":"有人"}]
2.http://localhost/book/randomList, 随机查询一条图书;
3.http://localhost/book/list2,搜索图书名称:五: