本文已参与「新人创作礼」活动,一起开启掘金创作之路。
SpringDataJpa的使用 -- 条件查询、排序查询、分页查询 二
上一篇文章:SpringDataJpa的使用 -- 条件查询、排序查询、分页查询 - 掘金 (juejin.cn)
本文在前文的基础上补充了 条件查询、分组查询、统计查询 的其他实现方法。
同时,添加了前文所没有的 指定查询属性
,其他的方法基本都是查询全部字段的。
实体类不变,nullable = false
不是必须的;Repository 接口 大体一致。
Article.java
/**
* 文章 类
*
* @author LJM
*/
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "ARTICLE")
public class Article {
/**
* 文章 id
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "article_id", nullable = false)
private Long articleId;
/**
* 文章 标题
*/
@Column(name = "article_title")
private String articleTitle;
/**
* 文章 内容
*/
@Column(name = "article_content")
private String articleContent;
/**
* 文章 类型
*/
@Column(name = "article_type")
private String articleType;
/**
* 文章 阅读量
*/
@Column(name = "article_read_number")
private Integer articleReadNumber;
/**
* 文章 点赞数
*/
@Column(name = "article_likes_number")
private Integer articleLikesNumber;
/**
* 多对一
* 多方
* 作者外键
* 维护方
*/
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "article_author_id")
private Author author;
/**
* 省略了其他的 构造函数
*/
}
ArticleRepository.java
/**
* 文章 操作 接口
*
* @author l'j'm
*/
public interface ArticleRepository extends JpaRepository<Article, Long>, JpaSpecificationExecutor<Article> {
}
再继承了一个和 JpaRepository 同包的接口 JpaSpecificationExecutor,
须知
本文引入新接口和方法,需要先行简述所需要的参数,方便阅读。
entityManager,用于与持久化上下文交互的接口。
-
其中对于任何持久性实体身份都有一个唯一的实体实例。就是说,每一次 数据持久化操作都有一个唯一的 entityManager 来完成该功能。
-
在持久性上下文中,entityManager 管理实体实例及其生命周期。
-
在 Spring Boot 中 通过 @Resource 即可获取。
@Resource
private EntityManager entityManager;
CriteriaBuilder,是一个泛型,可以理解为:构建条件查询 HQL 语句的构造器。
下面是获得该类对象的方法,其中 entityManager 是前面提到的 持久化管理对象。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery,是一个泛型,可以理解为:添加条件查询构建好的 HQL 语句。
下面是获得该类对象的方法,其中 criteriaBuilder 前面获得的 查询条件构造器。
CriteriaQuery<Article> criteriaQuery = criteriaBuilder.createQuery(class);
Specification,是一个泛型,可以理解为存储查询条件的类。
下面是创建该类对象的方法,其中 CriteriaQuery、CriteriaBuilder 就是前面提到的 查询语句和查询构造器,在方法里已经创建好了,不需要我们关心。
Specification<Article> criteriaQueryBuilder = new Specification<Article>() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
// 内容
}
};
Root,是一个泛型,from 子句中的根类型,查询根始终引用实体,可以理解为:用于构建查询条件键值对。
- 根据属性名在设定好的实体类中找到它,并添加到 查询语句 上。
条件查询
法一在上一篇文章中提到了,是用 JpaRepository 提供的,通过使用关键字来实现的条件查询。
仅条件查询
-
是继承 JpaSpecificationExecutor 接口,使用 findAll(@Nullable Specification) 方法。
-
首先创建一个 Specification 对象,再将对象传入 findAll() 中。
@Test
public void aVoid1() {
Specification<Article> criteriaQueryBuilder = (root, query, criteriaBuilder)
-> criteriaBuilder.equal(root.get("articleType"), "后端");
List<Article> articleList = articleRepository.findAll(criteriaQueryBuilder);
System.out.println("====== 后端 ======");
articleList.stream().map(Objects::toString).forEach(System.out::println);
Specification<Article> criteriaQueryBuilder1 = (root, query, criteriaBuilder) -> {
Predicate predicate = criteriaBuilder.equal(root.get("articleType"), "后端");
Predicate predicate1 = criteriaBuilder.like(root.get("articleContent"), "%好%");
return criteriaBuilder.and(predicate, predicate1);
};
List<Article> articleList1 = articleRepository.findAll(criteriaQueryBuilder1);
System.out.println("====== 后端,部分内容 ======");
articleList1.stream().map(Objects::toString).forEach(System.out::println);
}
root
用于构建查询条件键值对;query
用于组装查询语句;criteriaBuilder
用于构建查询语句。
条件查询并排序、分页
-
同上文一样,JpaSpecificationExecutor 接口的 findAll() 方法还有 findAll(@Nullable Specification, Sort)、findAll(@Nullable Specification, Pageable) 这两种。
-
Sort 是排序条件;Pageable 是分页条件。
-
需要分页并排序时,将 Sort 放入 Pageable 中,再把 Pageable 传入 findAll() 方法中。
-
例子
@Test
public void aVoid2() {
Specification<Article> criteriaQueryBuilder = (root, query, criteriaBuilder)
-> criteriaBuilder.equal(root.get("articleType"), "后端");
Pageable pageable1 = PageRequest.of(0, 4);
Page<Article> articleList = articleRepository.findAll(criteriaQueryBuilder, pageable1);
System.out.println("====== 后端并分页 ======");
articleList.stream().map(Objects::toString).forEach(System.out::println);
Specification<Article> criteriaQueryBuilder1 = (root, query, criteriaBuilder) -> {
Predicate predicate = criteriaBuilder.equal(root.get("articleType"), "后端");
Predicate predicate1 = criteriaBuilder.like(root.get("articleContent"), "%好%");
return criteriaBuilder.and(predicate, predicate1);
};
Pageable pageable2 = PageRequest.of(0, 4);
Page<Article> articleList2 = articleRepository.findAll(criteriaQueryBuilder1, pageable2);
System.out.println("====== 后端,部分内容 并排序 ======");
articleList2.stream().map(Objects::toString).forEach(System.out::println);
Pageable pageable3 = PageRequest.of(0, 4, Sort.by("articleReadNumber").ascending());
Page<Article> articleList3 = articleRepository.findAll(criteriaQueryBuilder1, pageable3);
System.out.println("====== 后端,部分内容 并分页排序 ======");
articleList3.stream().map(Objects::toString).forEach(System.out::println);
}
- 构建出来的 查询语句 是 HQL 语句。
(二发)如果对你有帮助,点赞可好!!