1、概览 {#1概览}
本文将带你了解 Spring Data 3 中引入的新 Repository 接口。
Spring Data 3 引入了基于 List 的 CRUD Repository 接口,可用于替换返回 Iterable 的现有 CRUD Repository 接口。此外,分页和排序接口默认不继承原始 CRUD Repository,而是由用户自己选择。接下来看看这些接口与现有接口有何不同,以及如何使用它们。
2、项目设置 {#2项目设置}
首先创建一个 Spring Boot 应用,其中包含一个简单的实体和将使用新接口的 Repository。
2.1、依赖 {#21依赖}
首先,为项目添加所需的 spring-boot-starter-data-jpa 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.2.3</version>
</dependency>
除此之外,还要配置数据库。可以使用任何 SQL 数据库,本文将使用 H2 内存数据库:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
2.2、Entity {#22entity}
创建一个 Book 实体:
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String author;
private String isbn;
// 构造器、Getter、Setter
}
有了实体后,来看看如何使用新接口与数据库交互。
3、基于 List 的 Repository {#3基于-list-的-repository}
Spring Data 3 引入了一组新的 CRUD Repository 接口,可返回实体列表。这些接口与现有接口类似,只是它们返回的是 List 而不是 Iterable。这使我们能够使用 List 接口的高级方法,如 get() 和 indexOf()。
3.1、Spring Data 3 中新增了三个接口 {#31spring-data-3-中新增了三个接口}
ListCrudRepository 接口提供了基本 CRUD 操作方法,如 save()、delete() 和 findById()。ListCrudRepository 与基于 Iterable 的对应 Repository 的主要区别在于,返回值现在是 List,这使我们可以对返回的数据执行更高级的操作。
ListQuerydslPredicateExecutor 接口提供了使用 Querydsl Predicate 执行查询的方法。Querydsl 是一个允许在 Java 中构建类型安全的 SQL 类查询的框架。通过 ListQuerydslPredicateExecutor,我们可以执行 Querydsl 查询并以 List 形式返回结果。
ListQueryByExampleExecutor 接口提供了使用 Example 实体执行查询并以 List 形式返回结果的方法。Example 实体是指包含我们想用来搜索其他实体的值的实体。例如,如果我们有一个 title 为 Spring Data 的 Book 实体,我们就可以创建一个 title 为 Spring Data 的示例实体,并用它来搜索 title 相同的其他 Book。
3.2、ListCrudRepository {#32listcrudrepository}
来详细看看 ListCrudRepository 接口。首先,创建一个使用该接口与数据库交互的 Repository:
@Repository
public interface BookListRepository extends ListCrudRepository<Book, Long> {
List<Book> findBooksByAuthor(String author);
}
上述 Repository 继承了 ListCrudRepository 接口,为我们提供了基本的 CRUD 方法。我们可以使用现有的 Repository 方法来保存、删除和查找数据库中的 Book。
除这些方法外,还自定义了 findBooksByAuthor() 方法,用于按 author 查找 Book。
3.3、使用基于 List 的 Repository {#33使用基于-list-的-repository}
来看看如何使用该 Repository 与数据库交互:
@SpringBootTest
public class BookListRepositoryIntegrationTest {
@Autowired
private BookListRepository bookListRepository;
@Test
public void givenDbContainsBooks_whenFindBooksByAuthor_thenReturnBooksByAuthor() {
Book book1 = new Book("Spring Data", "John Doe", "1234567890");
Book book2 = new Book("Spring Data 2", "John Doe", "1234567891");
Book book3 = new Book("Spring Data 3", "John Doe", "1234567892");
bookListRepository.saveAll(Arrays.asList(book1, book2, book3));
List&lt;Book&gt; books = bookListRepository.findBooksByAuthor(&quot;John Doe&quot;);
Assert.assertEquals(3, books.size());
}
}
首先创建了三个 Boot 实体,并将它们保存到数据库中。然后,使用 findBooksByAuthor() 方法查找 author为 John Doe 的所有 Book。最后,验证返回的 List 是否包含所创建的三个 Boot 实体。
注意,我们在返回的 List 上调用 了 size() 方法。如果 Repository 使用基于 Iterable 的接口,就不可能这样做,因为 Iterable 接口未提供 size() 方法。
4、排序接口 {#4排序接口}
为了能够使用新的基于 List 的接口,Spring Data 3 必须对现有的排序接口进行更改。 PagingAndSortingRepository 不再继承旧的 CrudRepository。相反,用户可以选择在继承排序接口的同时继承新的基于 List 的接口或基于 Iterable 的接口。
4.1、PagingAndSortingRepository {#41pagingandsortingrepository}
来看看,PagingAndSortingRepository 接口,创建一个使用该接口与数据库交互的 Repository:
@Repository
public interface BookPagingAndSortingRepository extends PagingAndSortingRepository<Book, Long>, ListCrudRepository<Book, Long> {
List<Book> findBooksByAuthor(String author, Pageable pageable);
}
上述 Repository 继承了 ListCrudRepository 接口,该接口为我们提供了基本的 CRUD 方法。除此之外,还继承了 PagingAndSortingRepository 接口,它为我们提供了排序和分页方法。
在 Spring Data 的旧版本中,不需要明确继承 CrudRepository 接口。只有排序和分页接口就足够了。这里还定义了一个名为 findBooksByAuthor() 的新方法,它接收一个 Pageable 参数并返回一个 List<Book>。
接下来,看看如何使用该方法对结果进行排序和分页。
4.2、使用排序 Repository 接口 {#42使用排序-repository-接口}
使用该 Repository 与数据库交互:
@SpringBootTest
public class BookPagingAndSortingRepositoryIntegrationTest {
@Autowired
private BookPagingAndSortingRepository bookPagingAndSortingRepository;
@Test
public void givenDbContainsBooks_whenfindBooksByAuthor_thenReturnBooksByAuthor() {
Book book1 = new Book("Spring Data", "John Doe", "1234567890");
Book book2 = new Book("Spring Data 2", "John Doe", "1234567891");
Book book3 = new Book("Spring Data 3", "John Doe", "1234567892");
bookPagingAndSortingRepository.saveAll(Arrays.asList(book1, book2, book3));
Pageable pageable = PageRequest.of(0, 2, Sort.by(&quot;title&quot;).descending());
List&lt;Book&gt; books = bookPagingAndSortingRepository.findBooksByAuthor(&quot;John Doe&quot;, pageable);
Assert.assertEquals(2, books.size());
Assertions.assertEquals(book3.getId(), books.get(0).getId());
Assertions.assertEquals(book2.getId(), books.get(1).getId());
}
}
和之前一样,我们首先创建了三个 Book 实体,并将它们保存到数据库中。然后,使用 findBooksByAuthor() 方法查找 author 为 John Doe 的所有书籍。但这次,我们向该方法传递了一个 Pageable 对象,按 title 降序排序,并只返回前两个结果。
最后,验证返回的 List 是否包含之前创建的两个 Book 实体。还验证了 Book 是按 title 降序排序的,因此 title 为 Spring Data 3 的书首先返回,标题为 Spring Data 2 的书其次返回。
4.3、其他排序接口 {#43其他排序接口}
除 PagingAndSortingRepository 接口外,还更改了以下接口:
ReactiveSortingRepository不再继承自ReactiveCrudRepositoryCoroutineSortingRepository不再继承自CoroutineCrudRepositoryRxJavaSortingRepository不再继承自RxJavaCrudRepository
5、总结 {#5总结}
本文介绍了在 Spring Data 3 中新增的基于 List 的 ListCrudRepository 接口,以及如何使用这些接口与数据库进行交互。还介绍了对现有排序接口所做的更改,以便能够同时使用新的 ListCrudRepository 的接口。
Ref:https://www.baeldung.com/spring-data-3-crud-repository-interfaces
51工具盒子