首页 > 编程 > Java > 正文

在Spring Boot中使用Spring-data-jpa实现分页查询

2019-11-26 11:48:55
字体:
来源:转载
供稿:网友

在我们平时的工作中,查询列表在我们的系统中基本随处可见,那么我们如何使用jpa进行多条件查询以及查询列表分页呢?下面我将介绍两种多条件查询方式。

1、引入起步依赖  

<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> 

2、对thymeleaf和jpa进行配置

打开application.yml,添加以下参数,以下配置在之前的文章中介绍过,此处不做过多说明

spring:  thymeleaf:  cache: true  check-template-location: true  content-type: text/html  enabled: true  encoding: utf-8  mode: HTML5  prefix: classpath:/templates/  suffix: .html  excluded-view-names:  template-resolver-order:  datasource:   driver-class-name: com.mysql.jdbc.Driver   url: jdbc:mysql://localhost:3306/restful?useUnicode=true&characterEncoding=UTF-8&useSSL=false   username: root   password: root   initialize: true  init-db: true  jpa:   database: mysql   show-sql: true   hibernate:   ddl-auto: update   naming:    strategy: org.hibernate.cfg.ImprovedNamingStrategy 

3、编写实体Bean

@Entity @Table(name="book") public class Book {  @Id  @GeneratedValue(strategy = GenerationType.IDENTITY)  @Column(name = "id", updatable = false)  private Long id;  @Column(nullable = false,name = "name")  private String name;  @Column(nullable = false,name = "isbn")  private String isbn;  @Column(nullable = false,name = "author")  private String author;  public Book (String name,String isbn,String author){   this.name = name;   this.isbn = isbn;   this.author = author;  }  public Book(){  }  //此处省去get、set方法 } public class BookQuery {  private String name;  private String isbn;  private String author;  //此处省去get、set方法 } 

4、编写Repository接口

@Repository("bookRepository") public interface BookRepository extends JpaRepository<Book,Long>   ,JpaSpecificationExecutor<Book> { } 

此处继承了两个接口,后续会介绍为何会继承这两个接口

5、抽象service层

首先抽象出接口

public interface BookQueryService {  Page<Book> findBookNoCriteria(Integer page,Integer size);  Page<Book> findBookCriteria(Integer page,Integer size,BookQuery bookQuery); } 

实现接口

@Service(value="https://my.oschina.net/wangxincj/blog/bookQueryService") public class BookQueryServiceImpl implements BookQueryService {  @Resource  BookRepository bookRepository;  @Override  public Page<Book> findBookNoCriteria(Integer page,Integer size) {   Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");   return bookRepository.findAll(pageable);  }  @Override  public Page<Book> findBookCriteria(Integer page, Integer size, final BookQuery bookQuery) {   Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");   Page<Book> bookPage = bookRepository.findAll(new Specification<Book>(){    @Override    public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {     List<Predicate> list = new ArrayList<Predicate>();     if(null!=bookQuery.getName()&&!"".equals(bookQuery.getName())){      list.add(criteriaBuilder.equal(root.get("name").as(String.class), bookQuery.getName()));     }     if(null!=bookQuery.getIsbn()&&!"".equals(bookQuery.getIsbn())){      list.add(criteriaBuilder.equal(root.get("isbn").as(String.class), bookQuery.getIsbn()));     }     if(null!=bookQuery.getAuthor()&&!"".equals(bookQuery.getAuthor())){      list.add(criteriaBuilder.equal(root.get("author").as(String.class), bookQuery.getAuthor()));     }     Predicate[] p = new Predicate[list.size()];     return criteriaBuilder.and(list.toArray(p));    }   },pageable);   return bookPage;  } } 

    此处我定义了两个接口,findBookNoCriteria是不带查询条件的,findBookCriteria是带查询条件的。在此处介绍一下上面提到的自定义Repository继承的两个接口,如果你的查询列表是没有查询条件,只是列表展示和分页,只需继承JpaRepository接口即可,但是如果你的查询列表是带有多个查询条件的话则需要继承JpaSpecificationExecutor接口,这个接口里面定义的多条件查询的方法。当然不管继承哪个接口,当你做分页查询时,都是需要调用findAll方法的,这个方法是jap定义好的分页查询方法。

findBookCriteria方法也可以使用以下方法实现,大家可以自行选择

@Override  public Page<Book> findBookCriteria(Integer page, Integer size, final BookQuery bookQuery) {   Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");   Page<Book> bookPage = bookRepository.findAll(new Specification<Book>(){    @Override    public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {     Predicate p1 = criteriaBuilder.equal(root.get("name").as(String.class), bookQuery.getName());     Predicate p2 = criteriaBuilder.equal(root.get("isbn").as(String.class), bookQuery.getIsbn());     Predicate p3 = criteriaBuilder.equal(root.get("author").as(String.class), bookQuery.getAuthor());     query.where(criteriaBuilder.and(p1,p2,p3));     return query.getRestriction();    }   },pageable);   return bookPage;  } 

6、编写Controller

针对有查询条件和无查询条件,我们分别编写一个Controller,默认每页显示5条,如下

@Controller @RequestMapping(value = "https://my.oschina.net/queryBook") public class BookController {  @Autowired  BookQueryService bookQueryService;  @RequestMapping("/findBookNoQuery")  public String findBookNoQuery(ModelMap modelMap,@RequestParam(value = "https://my.oschina.net/wangxincj/blog/page", defaultValue = "https://my.oschina.net/wangxincj/blog/0") Integer page,       @RequestParam(value = "https://my.oschina.net/wangxincj/blog/size", defaultValue = "https://my.oschina.net/wangxincj/blog/5") Integer size){   Page<Book> datas = bookQueryService.findBookNoCriteria(page, size);   modelMap.addAttribute("datas", datas);   return "index1";  }  @RequestMapping(value = "https://my.oschina.net/findBookQuery",method = {RequestMethod.GET,RequestMethod.POST})  public String findBookQuery(ModelMap modelMap, @RequestParam(value = "https://my.oschina.net/wangxincj/blog/page", defaultValue = "https://my.oschina.net/wangxincj/blog/0") Integer page,         @RequestParam(value = "https://my.oschina.net/wangxincj/blog/size", defaultValue = "https://my.oschina.net/wangxincj/blog/5") Integer size, BookQuery bookQuery){   Page<Book> datas = bookQueryService.findBookCriteria(page, size,bookQuery);   modelMap.addAttribute("datas", datas);   return "index2";  } } 

7、编写页面

首先我们编写一个通用的分页页面,新建一个叫page.html的页面

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"   xmlns:th="http://www.thymeleaf.org"   xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"   layout:decorator="page"> <body> <div th:fragment="pager">  <div class="text-right" th:with="baseUrl=${#httpServletRequest.getRequestURL().toString()},pars=${#httpServletRequest.getQueryString() eq null ? '' : new String(#httpServletRequest.getQueryString().getBytes('iso8859-1'), 'UTF-8')}">   <ul style="margin:0px;" class="pagination" th:with="newPar=${new Java.lang.String(pars eq null ? '' : pars).replace('page='+(datas.number), '')},             curTmpUrl=${baseUrl+'?'+newPar},             curUrl=${curTmpUrl.endsWith('&') ? curTmpUrl.substring(0, curTmpUrl.length()-1):curTmpUrl}" >    <!--<li th:text="${pars}"></li>-->    <li><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=0)}" rel="external nofollow" >首页</a></li>    <li th:if="${datas.hasPrevious()}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number-1})}" rel="external nofollow" >上一页</a></li>    <!--总页数小于等于10-->    <div th:if="${(datas.totalPages le 10) and (datas.totalPages gt 0)}" th:remove="tag">     <div th:each="pg : ${#numbers.sequence(0, datas.totalPages - 1)}" th:remove="tag">       <span th:if="${pg eq datas.getNumber()}" th:remove="tag">        <li class="active"><span class="current_page line_height" th:text="${pg+1}">${pageNumber}</span></li>       </span>      <span th:unless="${pg eq datas.getNumber()}" th:remove="tag">        <li><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${pg})}" rel="external nofollow" th:text="${pg+1}"></a></li>       </span>     </div>    </div>    <!-- 总数数大于10时 -->    <div th:if="${datas.totalPages gt 10}" th:remove="tag">     <li th:if="${datas.number-2 ge 0}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number}-2)}" rel="external nofollow" th:text="${datas.number-1}"></a></li>     <li th:if="${datas.number-1 ge 0}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number}-1)}" rel="external nofollow" th:text="${datas.number}"></a></li>     <li class="active"><span class="current_page line_height" th:text="${datas.number+1}"></span></li>     <li th:if="${datas.number+1 lt datas.totalPages}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number}+1)}" rel="external nofollow" th:text="${datas.number+2}"></a></li>     <li th:if="${datas.number+2 lt datas.totalPages}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number}+2)}" rel="external nofollow" th:text="${datas.number+3}"></a></li>    </div>    <li th:if="${datas.hasNext()}"><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.number+1})}" rel="external nofollow" >下一页</a></li>    <!--<li><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/@{${curUrl}(page=${datas.totalPages-1})}" rel="external nofollow" >尾页</a></li>-->    <li><a href="https://my.oschina.net/wangxincj/blog/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" th:href="https://my.oschina.net/wangxincj/blog/${datas.totalPages le 0 ? curUrl+'page=0':curUrl+'&page='+(datas.totalPages-1)}" rel="external nofollow" >尾页</a></li>    <li><span th:utext="'共'+${datas.totalPages}+'页 / '+${datas.totalElements}+' 条'"></span></li>   </ul>  </div> </div> </body> </html> 

针对无查询条件的接口,创建一个名为index1.html的页面并引入之前写好的分页页面,如下

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head>  <meta charset="UTF-8"/>  <title>Title</title>  <script type="text/javascript" th:src="https://my.oschina.net/wangxincj/blog/@{/jquery-1.12.3.min.js}"></script>  <script type="text/javascript" th:src="https://my.oschina.net/wangxincj/blog/@{/bootstrap/js/bootstrap.min.js}"></script>  <link type="text/css" rel="stylesheet" th:href="https://my.oschina.net/wangxincj/blog/@{/bootstrap/css/bootstrap-theme.min.css}" rel="external nofollow" rel="external nofollow" />  <link type="text/css" rel="stylesheet" th:href="https://my.oschina.net/wangxincj/blog/@{/bootstrap/css/bootstrap.css}" rel="external nofollow" rel="external nofollow" /> </head> <body>  <table class="table table-hover">   <thead>   <tr>    <th>ID</th>    <th>name</th>    <th>isbn</th>    <th>author</th>   </tr>   </thead>   <tbody>   <tr th:each="obj : ${datas}">    <td th:text="${obj.id}">${obj.id}</td>    <td th:text="${obj.name}">${obj.name}</td>    <td th:text="${obj.isbn}">${obj.isbn}</td>    <td th:text="${obj.name}">${obj.author}</td>   </tr>   </tbody>  </table>   <div th:include="page :: pager" th:remove="tag"></div> </body> </html> 

     针对有查询条件的接口,创建一个名为index2.html的页面并引入之前写好的分页页面,如下  

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head>  <meta charset="UTF-8"/>  <title>Title</title>  <script type="text/javascript" th:src="https://my.oschina.net/wangxincj/blog/@{/jquery-1.12.3.min.js}"></script>  <script type="text/javascript" th:src="https://my.oschina.net/wangxincj/blog/@{/bootstrap/js/bootstrap.min.js}"></script>  <link type="text/css" rel="stylesheet" th:href="https://my.oschina.net/wangxincj/blog/@{/bootstrap/css/bootstrap-theme.min.css}" rel="external nofollow" rel="external nofollow" />  <link type="text/css" rel="stylesheet" th:href="https://my.oschina.net/wangxincj/blog/@{/bootstrap/css/bootstrap.css}" rel="external nofollow" rel="external nofollow" /> </head> <body> <form th:action="@{/queryBook/findBookQuery}" th:object="${bookQuery}" th:method="get">  <div class="form-group">   <label class="col-sm-2 control-label" >name</label>   <div class="col-sm-4">    <input type="text" class="form-control" id="name" placeholder="请输入名称" th:field="*{name}"/>   </div>   <label class="col-sm-2 control-label">isbn</label>   <div class="col-sm-4">    <input type="text" class="form-control" id="isbn" placeholder="请输ISBN" th:field="*{isbn}"/>   </div>  </div>  <div class="form-group">   <label class="col-sm-2 control-label" >author</label>   <div class="col-sm-4">    <input type="text" class="form-control" id="author" placeholder="请输author" th:field="*{author}"/>   </div>   <div class="col-sm-4">    <button class="btn btn-default" type="submit" placeholder="查询">查询</button>   </div>  </div> </form>  <table class="table table-hover">   <thead>   <tr>    <th>ID</th>    <th>name</th>    <th>isbn</th>    <th>author</th>   </tr>   </thead>   <tbody>   <tr th:each="obj : ${datas}">    <td th:text="${obj.id}">${obj.id}</td>    <td th:text="${obj.name}">${obj.name}</td>    <td th:text="${obj.isbn}">${obj.isbn}</td>    <td th:text="${obj.name}">${obj.author}</td>   </tr>   </tbody>  </table>   <div th:include="page :: pager" th:remove="tag"></div> </body> </html> 

ok!代码都已经完成,我们将项目启动起来,看一下效果。大家可以往数据库中批量插入一些数据,访问

http://localhost:8080/queryBook/findBookNoQuery,显示如下页面

访问http://localhost:8080/queryBook/findBookQuery,显示页面如下,可以输入查询条件进行带条件的分页查询:

总结

以上所述是小编给大家介绍的在Spring Boot中使用Spring-data-jpa实现分页查询,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表