2019独角兽企业重金招聘Python工程师标准>>>
上一篇我们简单介绍了在spring Boot中使用Spring-data-jpa操作数据库,本篇着重讲一下如何使用jpa进行分页。
在我们平时的工作中,查询列表在我们的系统中基本随处可见,那么我们如何使用jpa进行多条件查询以及查询列表分页呢?下面我将介绍两种多条件查询方式。
1、引入起步依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-data-jpa
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
,JpaSpecificationExecutor {
}
此处继承了两个接口,后续会介绍为何会继承这两个接口
5、抽象service层
首先抽象出接口
public interface BookQueryService {
Page findBookNoCriteria(Integer page,Integer size);
Page findBookCriteria(Integer page,Integer size,BookQuery bookQuery);
}
实现接口
@Service(value="bookQueryService")
public class BookQueryServiceImpl implements BookQueryService {
@Resource
BookRepository bookRepository;
@Override
public Page findBookNoCriteria(Integer page,Integer size) {
Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");
return bookRepository.findAll(pageable);
}
@Override
public Page findBookCriteria(Integer page, Integer size, final BookQuery bookQuery) {
Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");
Page bookPage = bookRepository.findAll(new Specification(){
@Override
public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
List list = new ArrayList();
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 findBookCriteria(Integer page, Integer size, final BookQuery bookQuery) {
Pageable pageable = new PageRequest(page, size, Sort.Direction.ASC, "id");
Page bookPage = bookRepository.findAll(new Specification(){
@Override
public Predicate toPredicate(Root 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 = "/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 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 datas = bookQueryService.findBookCriteria(page, size,bookQuery);
modelMap.addAttribute("datas", datas);
return "index2";
}
}
7、编写页面
首先我们编写一个通用的分页页面,新建一个叫page.html的页面
针对无查询条件的接口,创建一个名为index1.html的页面并引入之前写好的分页页面,如下
Title
ID
name
isbn
author
${obj.id}
${obj.name}
${obj.isbn}
${obj.author}
针对有查询条件的接口,创建一个名为index2.html的页面并引入之前写好的分页页面,如下
Title
ID
name
isbn
author
${obj.id}
${obj.name}
${obj.isbn}
${obj.author}
ok!代码都已经完成,我们将项目启动起来,看一下效果。大家可以往数据库中批量插入一些数据,访问http://localhost:8080/queryBook/findBookNoQuery,显示如下页面
访问http://localhost:8080/queryBook/findBookQuery,显示页面如下,可以输入查询条件进行带条件的分页查询:
ok!以上便是一个简单的jap分页查询功能的实现。