在SpringBoot中使⽤Spring-data-jpa实现分页查询
在我们平时的⼯作中,查询列表在我们的系统中基本随处可见,那么我们如何使⽤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进⾏配置
打开l,添加以下参数,以下配置在之前的⽂章中介绍过,此处不做过多说明
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: sql.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="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!=Name()&&!"".Name())){
list.add(criteriaBuilder.("name").as(String.class), Name()));
}
if(null!=Isbn()&&!"".Isbn())){
list.add(criteriaBuilder.("isbn").as(String.class), Isbn()));
}
if(null!=Author()&&!"".Author())){
list.add(criteriaBuilder.("author").as(String.class), Author()));
}
Predicate[] p = new Predicate[list.size()];
return criteriaBuilder.Array(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.("name").as(String.class), Name());
Predicate p2 = criteriaBuilder.("isbn").as(String.class), Isbn());
Predicate p3 = criteriaBuilder.("author").as(String.class), Author());
query.where(criteriaBuilder.and(p1,p2,p3));
Restriction();
}
},pageable);
return bookPage;
}
6、编写Controller
针对有查询条件和⽆查询条件,我们分别编写⼀个Controller,默认每页显⽰5条,如下
@Controller
@RequestMapping(value = "/queryBook")
public class BookController {
@Autowired
BookQueryService bookQueryService;
@RequestMapping("/findBookNoQuery")
public String findBookNoQuery(ModelMap modelMap,@RequestParam(value = "page", defaultValue = "0") Integer page, @RequestParam(value = "size", defaultValue = "5") Integer size){
Page<Book> datas = bookQueryService.findBookNoCriteria(page, size);
modelMap.addAttribute("datas", datas);
return "index1";
}
@RequestMapping(value = "/findBookQuery",method = {RequestMethod.GET,RequestMethod.POST})
public String findBookQuery(ModelMap modelMap, @RequestParam(value = "page", defaultValue = "0") Integer page, @RequestParam(value = "size", defaultValue = "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="/1999/xhtml"
xmlns:th=""
xmlns:layout="/thymeleaf/layout"
layout:decorator="page">
<body>
<div th:fragment="pager">
<div class="text-right" th:with="baseUrl=${#RequestURL().toString()},pars=${#QueryString() eq null ? '' : new Strin <ul class="pagination" th:with="newPar=${new java.lang.String(pars eq null ? '' : pars).replace('page='+(datas.number), '')},
curTmpUrl=${baseUrl+'?'+newPar},
curUrl=${dsWith('&') ? curTmpUrl.substring(0, curTmpUrl.length()-1):curTmpUrl}" >
<!--<li th:text="${pars}"></li>-->
<li><a href="#" th:href="@{${curUrl}(page=0)}">⾸页</a></li>
<li th:if="${datas.hasPrevious()}"><a href="#" th:href="@{${curUrl}(page=${datas.number-1})}">上⼀页</a></li>
<!--总页数⼩于等于10-->
<div th:if="${(alPages le 10) and (alPages gt 0)}" th:remove="tag">
<div th:each="pg : ${#numbers.sequence(0, alPages - 1)}" th:remove="tag">
<span th:if="${pg Number()}" th:remove="tag">
<li class="active"><span class="current_page line_height" th:text="${pg+1}">${pageNumber}</span></li>
</span>
<span th:unless="${pg Number()}" th:remove="tag">
<li><a href="#" th:href="@{${curUrl}(page=${pg})}" th:text="${pg+1}"></a></li>
</span>
</div>
</div>
<!-- 总数数⼤于10时 -->
<div th:if="${alPages gt 10}" th:remove="tag">
<li th:if="${datas.number-2 ge 0}"><a href="#" th:href="@{${curUrl}(page=${datas.number}-2)}" th:text="${datas.number-1}"></a></li>
<li th:if="${datas.number-1 ge 0}"><a href="#" th:href="@{${curUrl}(page=${datas.number}-1)}" 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 alPages}"><a href="#" th:href="@{${curUrl}(page=${datas.number}+1)}" th:text="${datas.number+2}"></a></li> <li th:if="${datas.number+2 alPages}"><a href="#" th:href="@{${curUrl}(page=${datas.number}+2)}" th:text="${datas.number+3}"></a></li> </div>
<li th:if="${datas.hasNext()}"><a href="#" th:href="@{${curUrl}(page=${datas.number+1})}">下⼀页</a></li>
<!--<li><a href="#" th:href="@{${curUrl}(page=${alPages-1})}">尾页</a></li>-->
thymeleaf用法<li><a href="#" th:href="${alPages le 0 ? curUrl+'page=0':curUrl+'&page='+(alPages-1)}">尾页</a></li>
<li><span th:utext="'共'+${alPages}+'页 / '+${alElements}+' 条'"></span></li>
</ul>
</div>
</div>
</body>
</html>
针对⽆查询条件的接⼝,创建⼀个名为index1.html的页⾯并引⼊之前写好的分页页⾯,如下
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论