Spring-Data-jpa基本介绍
什么是spring-data-jpa
可以理解为JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL(Java Persistence Query Language)查询语言,属于Spring整个生态体系的一部分。随着Spring Boot和Spring Cloud在市场上的流行,Spring Data JPA也逐渐进入大家的视野,它们组成有机的整体,使用起来比较方便,加快了开发的效率,使开发者不需要关心和配置更多的东西,完全可以沉浸在Spring的完整生态标准实现下。JPA上手简单,开发效率高,对对象的支持比较好,又有很大的灵活性,市场的认可度越来越高。
********JPA是Java Persistence API的简称,********中文名为Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA包括以下3方面的内容:
(1)一套API标准。在javax.persistence的包下面,用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从烦琐的JDBC和SQL代码中解脱出来。
(2)面向对象的查询语言:Java Persistence QueryLanguage(JPQL)。这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密*****耦合***
(3)ORM(object/relational metadata)元数据的映射。JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。

Spring Data介绍
Spring Data项目是从2010年发展起来的,从创立之初SpringData就想提供一个大家熟悉的、一致的、基于Spring的数据访问编程模型,同时仍然保留底层数据存储的特殊特性。它可以轻松地让开发者使用数据访问技术,包括关系数据库、非关系数据库(NoSQL)和*****基于云的数据服务。***
Spring Data Common是Spring Data所有模块的公用部分,该项目提供跨Spring数据项目的共享基础设施。它包含了技术中立的库接口以及一个坚持java类的元数据模型。
*Spring Data不仅对传统的数据库访问技术JDBC、Hibernate、JDO、TopLick、JPA、Mybitas做了很好的支持、扩展、抽象、提供方**便的API,还对NoSQL等非关系数据做了很好的支持,包括MongoDB、***Redis、Apache Solr等
Spring Data操作的主要特性
Spring Data项目旨在为大家提供一种通用的编码模式。数据访问对象实现了对物理数据层的抽象,为编写查询方法提供了方便。通过对象映射,实现域对象和持续化存储之间的转换,而模板提供的是对底层存储实体的访问实现。如图1-4所示。操作上主要有如下特征:
提供模板操作,如Spring Data Redis和Spring Data Riak。
强大的Repository和定制的数据存储对象的抽象映射。 对数据访问对象的支持(Auting等)。
Spring-Data-JPA的结构图
七个Repository接口:
1. Repository
2. CrudRepository
3. PagingAndSortingRepository
4. QueryByExampleExecutor
5. JpaRepository
6. JpaSpeccificationExecutor
7. QueryDslPredicateExecutor
两个实现类:
1. SimpleJpaRepository
2. QueryDslJpaRepository
关系结构图如图1-5所示。

spring-data-jpa使用
快速上手
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
编写配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/news?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
password: root
username: root
jpa:
show-sql: true
database: mysql
hibernate:
ddl-auto: update
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #驼峰命名
NewsEntity.java
package com.springdatajpa2.pojo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity //表示是一个实体类
@Table(name = "news", schema = "newsdb", catalog = "")
@JsonIgnoreProperties(value={"hibernateLazyInitializer"}) //转json对象忽略空值
public class NewsEntity {
private int id;
private String typeId;
private String title;
private String publisher;
private String publisherFace;
private String content;
private Timestamp createTime;
private Timestamp updateTime;
private Integer deleted;
@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//指定主机的生成策略
@Column(name = "id") //指定字段和实体类属性的映射关系
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Basic
@Column(name = "type_id")
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
@Basic
@Column(name = "title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Basic
@Column(name = "publisher")
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
@Basic
@Column(name = "publisher_face")
public String getPublisherFace() {
return publisherFace;
}
public void setPublisherFace(String publisherFace) {
this.publisherFace = publisherFace;
}
@Basic
@Column(name = "content")
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Basic
@Column(name = "create_time")
public Timestamp getCreateTime() {
return createTime;
}
public void setCreateTime(Timestamp createTime) {
this.createTime = createTime;
}
@Basic
@Column(name = "update_time")
public Timestamp getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Timestamp updateTime) {
this.updateTime = updateTime;
}
@Basic
@Column(name = "deleted")
public Integer getDeleted() {
return deleted;
}
public void setDeleted(Integer deleted) {
this.deleted = deleted;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NewsEntity that = (NewsEntity) o;
return id == that.id &&
Objects.equals(typeId, that.typeId) &&
Objects.equals(title, that.title) &&
Objects.equals(publisher, that.publisher) &&
Objects.equals(publisherFace, that.publisherFace) &&
Objects.equals(content, that.content) &&
Objects.equals(createTime, that.createTime) &&
Objects.equals(updateTime, that.updateTime) &&
Objects.equals(deleted, that.deleted);
}
@Override
public String toString() {
return "NewsEntity{" +
"id=" + id +
", typeId='" + typeId + '\'' +
", title='" + title + '\'' +
", publisher='" + publisher + '\'' +
", publisherFace='" + publisherFace + '\'' +
", content='" + content + '\'' +
", createTime=" + createTime +
", updateTime=" + updateTime +
", deleted=" + deleted +
'}';
}
@Override
public int hashCode() {
return Objects.hash(id, typeId, title, publisher, publisherFace, content, createTime, updateTime, deleted);
}
}
NewsDao.java
package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
JpaSpecificationExecutor<NewsEntity> {
}
newsService.java
package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {
/**
* 添加新闻
*/
NewsEntity saveNews(NewsEntity newsEntity);
/**
* 修改新闻
*/
NewsEntity updateNews(NewsEntity newsEntity);
}
NewsServiceImpl.java
package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Transactional
public class NewsServiceImpl implements NewsService {
@Autowired
private NewsDao newsDao;
/**
* 添加新闻
*
* @param newsEntity
*/
@Override
public NewsEntity saveNews(NewsEntity newsEntity) {
return newsDao.save(newsEntity);
}
/**
* 修改新闻
*
* @param newsEntity
*/
@Override
public NewsEntity updateNews(NewsEntity newsEntity) {
return newsDao.save(newsEntity);
}
}
测试类
package com.springdatajpa2;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SpringDataJpa2ApplicationTests {
@Autowired
private NewsService newsService;
/**
* 新增
*/
@Test
void contextLoads() {
NewsEntity newsEntity = new NewsEntity();
newsEntity.setTypeId("1111");
newsEntity.setTitle("hhhhh");
newsService.saveNews(newsEntity);
}
/**
* 修改
*/
@Test
void contextLoads2() {
NewsEntity newsEntity = new NewsEntity();
newsEntity.setId(25);
newsEntity.setTypeId("1111");
newsEntity.setTitle("aaa");
newsService.updateNews(newsEntity);
}
}
方法命名查询
①查询的方法:find或get或read开头
②查询条件:用关键字链接,涉及属性首写字母大写
具体的查询方法命名规范如下: 1.findBy+属性名称(属性名称首字母大写,这种格式只能生成等值的查询条件) 举例:findByUserName=>select * from customer where userName=? 2.findBy+属性名称+查询方式(Like|IsNull|Equals|Between|LessThan|GreaterThan|OrderBy|Not|In等) 3.多条件查询:findBy+属性名称1+查询方式1+属性名称2+查询方式2[...]

举例:
getByIdAndUsername(int id,String username);
getById(int id);
getByIdLessThanEqual(int id);
getByGreaterThanEqual(int id);
getByUsernameLike(String str);
getByUsernameContaining(string str)
newsDao
package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
JpaSpecificationExecutor<NewsEntity> {
/*
以find开头
根据标题查询命名有规范
*/
List<NewsEntity> findByTitleLike(String title);
/**
以find开头
* 根据id查询
*/
NewsEntity findById(int id);
}
NewsService
package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {
/*
根据标题查询
*/
List<NewsEntity> findByTitleLike(String title);
/**
* 根据编号查询
*/
NewsEntity findById(int id);
}
NewsServiceImpl
package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class NewsServiceImpl implements NewsService {
@Autowired
private NewsDao newsDao;
/**
根据标题模糊查询
*/
@Override
public List<NewsEntity> findByTitleLike(String title) {
return newsDao.findByTitleLike("%"+title+"%");
}
/**
* 根据编号查询
*
* @param id
*/
@Override
public NewsEntity findById(int id) {
return newsDao.findById(id);
}
}
测试类
package com.springdatajpa2;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SpringDataJpa2ApplicationTests {
@Autowired
private NewsService newsService;
/**
* 根据标题模糊查询
*/
@Test
void contextLoads3() {
List<NewsEntity> 药 = newsService.findByTitleLike("药");
for (NewsEntity newsEntity : 药) {
System.out.println(newsEntity.toString());
}
}
/**
* 根据编号查询
*/
@Test
void contextLoads4() {
System.out.println(newsService.findById(10).toString());
}
}
多表查询

实体类
private Type type;
@ManyToOne(fetch = FetchType.EAGER)//多对一
@JoinColumn(name = "typeId",referencedColumnName = "id") //typeId对应实体的typeId id对应type类的id
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
NewsSwevice
/**
* 连表查询
* @return
*/
List<NewsEntity> findByTitle(String title);
NewsServiceImpl
/**
* 连表查询
* @return
*/
@Override
public List<NewsEntity> findByTitle(String title) {
NewsEntity newsEntity=new NewsEntity();
newsEntity.setTitle(title);
//newsEntity.setType(type);
//Type type = new Type();
ExampleMatcher title1 = ExampleMatcher.matching().withMatcher("title",
ExampleMatcher.GenericPropertyMatchers.contains());//模糊查询如果没有可以直接不要
Example<NewsEntity> entityExample=Example.of(newsEntity,title1);
return newsDao.findAll(entityExample);
}
测试类
/**
* 多表查询
*
*/
@Test
void contextLoads7() {
List<NewsEntity> 药 = newsService.findByTitle("");
for (NewsEntity newsEntity : 药) {
System.out.println(newsEntity.toString());
}
}
Query和Modifying注解
Query注解
jpql : 全称Java Persistence Query Language java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将JPQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。 其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的字段
举例:(from 类名 where 属性...)
select c from Customer c 或 select c from Customer as c 或 from Customer from Customer c where c.id = 1 from Customer c order by c.id desc (没有select,表示查询所有属性) select c.id, c.custName, c.custSource from Customer c select count(c.id) from Customer c group by cust_industry select max(c.id) from Customer c
前面说了,使用Spring-data-jpa进行开发的过程中,常用的功能,我们几乎不需要写一条jpql语句,复杂的功能,我们才需要自己写jpql语言。
自己写jpql语言就是通过@query注解来实现的:
- 没参数的@query查询:实现查找News中id最大的哪个记录返回相应对象:
@Query("select n from News n where n.id=(select max(ne.id) from News ne)")
News findNewsByMaxId();
-
带参数的@query查询,使用占位符:
@Query("select n from News n where n.title = ?1") List<News> findNewsByTitle(String title); -
带参数的@query查询,使用命名参数:
@Query("select n from News n where n.title = :title and n.publisher = :publisher") List<News> findNewsByTitleAndPublisher(String title, String publisher); -
带参数的@query查询,使用like的时候,是可以用%的,前面讲mybatis是不可以的但springdata可以:
@Query("select n from News n where n.title = :title and n.publisher like %:publisher%") List<News> findNewsByTitleAndPublisherLike(String title, String publisher); -
使用@query执行原生的sql查询:
@Query(value = "select * from news",nativeQuery = true) List<News> findAllByNativeQuery();
Modifying注解
在@Query注解的上面加上@Modifying,那么就可以执行update和delete的jpql语句了:
@Modifying
@Query("update News set title=?1 where id=?2")
void updateNews(String title, Integer id);
注意:直接执行这个方法是不行的,必须在service层里调用它才可以,原因是Springdata执行update和delete语句需要可写事务支持的,我们事务是放在service层的!Springdata需要事务,那么为什么前面的查询可以直接执行呢?默认情况下Springdata也是有事务的,只不过这个事务是只读事务,不能修改和删除数据库里的记录。另外还要注意一个问题,注解@Modifying是不能做insert语句的,jpql不支持!
NewsDao
package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
JpaSpecificationExecutor<NewsEntity> {
/**
* 根据标题和发布人查询,1代表第一个参数title,2代表第二个参数publisher
*/
@Query("from NewsEntity where title like %?1% and publisher=?2")
List<NewsEntity> getNewsEntityList(String title,String publisher);
/**
* 根据id修改标题
*/
@Modifying //根据id进行修改 不能写新增
@Query("update NewsEntity set title=?1 where id=?2")
void updateNewsEntityById(String title,int id);
}
NewsService
package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {
/**
* 根据标题和发布人查询
*/
List<NewsEntity> getNewsEntityList(String title,String publisher);
/**
* 根据id修改标题
*/
void updateNewsEntityById(String title,int id);
}
NewsServiceImpl
package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class NewsServiceImpl implements NewsService {
@Autowired
private NewsDao newsDao;
/**
* 根据标题和发布人查询
*/
@Override
public List<NewsEntity> getNewsEntityList(String title, String publisher) {
return newsDao.getNewsEntityList(title, publisher);
}
/**
* 根据id修改标题
*
* @param title
* @param id
*/
@Override
public void updateNewsEntityById(String title, int id) {
newsDao.updateNewsEntityById(title, id);
}
}
测试类
package com.springdatajpa2;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SpringDataJpa2ApplicationTests {
@Autowired
private NewsService newsService;
/**
* 标题和发布人查询
*/
@Test
void contextLoads5() {
List<NewsEntity> newsEntityList = newsService.getNewsEntityList("药", "科泰学院");
for (NewsEntity newsEntity : newsEntityList) {
System.out.println(newsEntity.toString());
}
}
/**
* 根据id修改标题
*
*/
@Test
void contextLoads6() {
newsService.updateNewsEntityById("bbb",25);
}
}
Spring-Data-Jpa分页查询排序
创建一个新的接口,继承PagingAndSortingRepository 接口,在接口中无需定义任何方法
public interface PageNewsRepository extends PagingAndSortingRepository<News,Integer> {
}
分页查询
@Override
public List<News> findAllByPage(Integer pageNum, Integer pageSize) {
//分页默认从0开始
Pageable pageable = PageRequest.of(pageNum-1, pageSize);
Page<News> page = pageNewsRepository.findAll(pageable);
System.out.println("当前页:"+page.getNumber()+1);
System.out.println("每页数量:"+page.getSize());
System.out.println("总页数:"+page.getTotalPages());
System.out.println("总记录数:"+page.getTotalElements());
System.out.println("当前记录:"+page.getContent());
return page.getContent();
}
排序
@Override
public List<News> findAllBySort() {
List<News> newsList = new ArrayList<>();
//按id降序
Sort sort = Sort.by(Sort.Direction.DESC, "id");
Iterable<News> newsIterable = pageNewsRepository.findAll(sort);
Iterator<News> iterator = newsIterable.iterator();
while (iterator.hasNext()) {
newsList.add(iterator.next());
}
return newsList;
}
先排序后分页
public List<News> findAllBySortAndPage() {
Integer pageNum=1;
Integer pageSize=5;
// Sort.Direction.DESC 排序规则 id: 用哪一个字段来排序
Sort sort = Sort.by(Sort.Direction.DESC, "id");
PageRequest pageable=PageRequest.of(pageNum-1,pageSize,sort);
Page<News> page = pageNewsRepository.findAll(pageable);
System.out.println("当前页 :" + page.getNumber() + 1);
System.out.println("每页显示数量:" + page.getSize());
System.out.println("总页数:" + page.getTotalPages());
System.out.println("总记录数:" + page.getTotalElements());
System.out.println("当前记录:" + page.getContent());
return page.getContent();
}
aa
有多个字段需要排序的时候
public List<News> findAllBySortAndPage() {
Integer pageNum=1;
Integer pageSize=5;
// Sort.Direction.DESC 排序规则 id: 用哪一个字段来排序
List<Sort.Order> orders= new ArrayList<>();
Sort.Order order1=new Sort.Order(Sort.Direction.DESC,"id");
Sort.Order order2=new Sort.Order(Sort.Direction.DESC,"name");
orders.add(order1);
orders.add(order2);
Sort sort = Sort.by(orders);
PageRequest pageable=PageRequest.of(pageNum-1,pageSize,sort);
Page<News> page = pageNewsRepository.findAll(pageable);
System.out.println("当前页 :" + page.getNumber() + 1);
System.out.println("每页显示数量:" + page.getSize());
System.out.println("总页数:" + page.getTotalPages());
System.out.println("总记录数:" + page.getTotalElements());
System.out.println("当前记录:" + page.getContent());
return page.getContent();
}
JpaRepository接口
创建JpaNewsRepository接口,继承JpaRepository接口,无需添加任何方法
public interface JpaNewsRepository extends JpaRepository<News, Integer> {
}
public void saveNews() {
News news = new News();
news.setTitle("这是一条没有灵魂的测试数据");
news.setContent("没有灵魂没有灵魂");
news.setTypeId("1001");
//有则修改,无则添加
jpaNewsRepository.saveAndFlush(news);
}
JpaSpecificationExecutor接口
paSpecificationExecutor这个接口和Repository接口不是一个家族的,它是用对象来写jpql语句的一个接口,内部的操作其实就是CriteriaQuery这种查询方法,JpaSpecificationExecutor接口里有下面的这些方法:
修改JpaNewsRepository的父接口如下:
public interface JpaNewsRepository extends JpaRepository<News, Integer>, JpaSpecificationExecutor<News> {
}
Java中类是不可以有多个父类的,但是接口是可以有多个父接口的
简单举一个例子,获取id>10的新闻记录:
public List<News> findCustomerAll(Integer id) {
/** Root : 要查询的实体类
* CriteriaQuery: query对象,基本上不用
* CriteriaBuilder: 构建的条件和条件连接词
*/
// 创建接口对象的内部类
Specification specification = new Specification<News>() {
@Override
public Predicate toPredicate(Root<News> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Path<Integer> path = root.get("id");
Predicate predicate = criteriaBuilder.lessThan(path, id);
return predicate;
}
};
return jpaNewsRepository.findAll(specification);
}
实现分页和动态条件查询效果:
1、dao层继承接口 JpaRepository<T,ID>和JpaSpecificationExecutor,无其他操作
public interface JpaNewsRepository extends JpaRepository<News, Integer>,JpaSpecificationExecutor<News> {
}
2、在service层添加动态条件查询的方法
@Override
public List<News> findAllByParam(News news, Integer pageNum) {
List<News> resultList = null;
Specification<News> querySpecifi = new Specification<News>() {
@Override
public Predicate toPredicate(Root<News> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
if (StringUtils.hasText(news.getTitle())) {
predicates.add(cb.like(root.get("title"), news.getTitle()));
}
if (StringUtils.hasText(news.getPublisher())) {
predicates.add(cb.equal(root.get("publisher"), news.getPublisher()));
}
// and到一起的话所有条件就是且关系,or就是或关系
return cb.and(predicates.toArray(new Predicate[0]));
}
};
PageRequest pageable= PageRequest.of(pageNum-1, 3);
resultList = this.jpaNewsRepository.findAll(querySpecifi,pageable).getContent();
return resultList;
}
3、controller层调用service层的方法
@GetMapping(value = "/findallbyparam")
public String findAll(News news, Integer pageNum) throws JsonProcessingException {
List<News> newsList = newsService.findAllByParam(news, pageNum);
return objectMapper.writeValueAsString(newsList);
}