1. 概述
在这个简短的教程中,我们将讨论Spring Data JPA Specification的一个高级功能,它允许我们在创建查询时连接表。
让首先我们简要回顾一下JPA Specifications及其用法。
2. JPA Specification
Spring Data JPA引入了Specification接口,允许我们使用可重用组件创建动态查询。
对于本文中的代码示例,我们将使用Author和Book类:
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
@OneToMany(cascade = CascadeType.ALL)
private List<Book> books;
// getters and setters
}
为了为Author实体创建动态查询,我们可以使用Specification接口的实现:
public class AuthorSpecifications {
public static Specification<Author> hasFirstNameLike(String name) {
return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("firstName"), "%" + name + "%");
}
public static Specification<Author> hasLastName(String name) {
return (root, query, cb) -> cb.equal(root.<String>get("lastName"), name);
}
}
最后,我们需要让AuthorRepository扩展JpaSpecificationExecutor:
@Repository
public interface AuthorsRepository extends JpaRepository<Author, Long>, JpaSpecificationExecutor<Author> {
}
因此,我们现在可以将这两个Specification链接在一起并使用它们创建查询:
@Test
void whenFindByLastNameAndFirstNameLike_thenOneAuthorIsReturned() {
Specification<Author> specification = hasLastName("Martin").and(hasFirstNameLike("Robert"));
List<Author> authors = repository.findAll(specification);
assertThat(authors).hasSize(1);
}
3. 使用JPA Specification连接表
我们可以从我们的数据模型中观察到Author实体与Book实体共享一对多关系:
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
// getters and setters
}
Criteria Query API允许我们在创建Specification时连接两个表。因此,我们将能够在我们的查询中包含来自Book实体的字段:
public static Specification<Author> hasBookWithTitle(String bookTitle) {
return (root, query, criteriaBuilder) -> {
Join<Book, Author> authorsBook = root.join("books");
return criteriaBuilder.equal(authorsBook.get("title"), bookTitle);
};
}
现在让我们将这个新Specification与之前创建的Specification组合起来:
@Test
void whenSearchingByBookTitleAndAuthorName_thenOneAuthorIsReturned() {
Specification<Author> specification = hasLastName("Martin").and(hasBookWithTitle("Clean Code"));
List<Author> authors = repository.findAll(specification);
assertThat(authors).hasSize(1);
}
最后,以下是生成的SQL语句,注意观察其中的JOIN子句:
select author0_.id as id1_1_,
author0_.first_name as first_na2_1_,
author0_.last_name as last_nam3_1_
from author author0_
inner join author_books books1_ on author0_.id = books1_.author_id
inner join book book2_ on books1_.books_id = book2_.id
where author0_.last_name = ?
and book2_.title = ?
4. 总结
在本文中,我们学习了如何使用JPA Specifications根据表的关联实体之一查询表。
Spring Data JPA的Specifications为创建查询提供了一种流式、动态和可重用的方式。
与往常一样,本教程的完整源代码可在GitHub上获得。
Show Disqus Comments
Post Directory
扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章