[翻译] 创建一个只读的Repository接口(Spring Data)
背景
在这个文章中,我们将讨论如何创建一个只读的Spring Data Repository。
有时有必要从数据库中读取数据而无需修改它。在这种情况下,拥有一个只读的Repository接口将是完美的。
它将提供读取数据的功能,不会有修改数据的风险。
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.3</version>
</dependency>
Spring Data受欢迎的CrudRepository接口包含在此依赖项中,该接口提供了大多数应用程序所需的所有基本CRUD操作(创建,读取,更新,删除)的方法。但是,它包含几种修改数据的方法,我们需要一个只能读取数据的存储库。
CrudRepository实际上扩展了另一个称为Repository的接口。我们还可以扩展此接口以满足我们的需求。
让我们创建一个继承Repository的新接口:
@NoRepositoryBean
public interface ReadOnlyRepository<T, ID> extends Repository<T, ID> {
Optional<T> findById(ID id);
List<T> findAll();
}
在这里,我们仅定义了两个只读方法。此存储库访问的实体将不受任何修改的影响。
还必须注意,我们必须使用@NoRepositoryBean批注来告诉Spring我们希望该存储库保持通用性,这一点也很重要。这使我们可以根据需要将只读存储库重用于许多不同的实体。
接下来,我们将看到如何将实体绑定到我们的新ReadOnlyRepository。
继承ReadOnlyRepository
假设我们有一个简单的Book实体,我们想访问它:
@Entity
public class Book {
@Id
@GeneratedValue
private Long id;
private String author;
private String title;
//getters and setters
}
现在我们有了一个可持久的实体,我们可以创建一个继承自ReadOnlyRepository的存储库接口:
public interface BookReadOnlyRepository extends ReadOnlyRepository<Book, Long> {
List<Book> findByAuthor(String author);
List<Book> findByTitle(String title);
}
除了它继承的两个方法外,我们还添加了两个特定于Book的只读方法:findByAuthor()和findByTitle()。总共,此存储库可以访问四种只读方法。
最后,让我们编写一个测试来确保BookReadOnlyRepository的功能:
@Test
public void givenBooks_whenUsingReadOnlyRepository_thenGetThem() {
Book aChristmasCarolCharlesDickens = new Book();
aChristmasCarolCharlesDickens.setTitle("A Christmas Carol");
aChristmasCarolCharlesDickens.setAuthor("Charles Dickens");
bookRepository.save(aChristmasCarolCharlesDickens);
Book greatExpectationsCharlesDickens = new Book();
greatExpectationsCharlesDickens.setTitle("Great Expectations");
greatExpectationsCharlesDickens.setAuthor("Charles Dickens");
bookRepository.save(greatExpectationsCharlesDickens);
Book greatExpectationsKathyAcker = new Book();
greatExpectationsKathyAcker.setTitle("Great Expectations");
greatExpectationsKathyAcker.setAuthor("Kathy Acker");
bookRepository.save(greatExpectationsKathyAcker);
List<Book> charlesDickensBooks = bookReadOnlyRepository.findByAuthor("Charles Dickens");
Assertions.assertEquals(2, charlesDickensBooks.size());
List<Book> greatExpectationsBooks = bookReadOnlyRepository.findByTitle("Great Expectations");
Assertions.assertEquals(2, greatExpectationsBooks.size());
List<Book> allBooks = bookReadOnlyRepository.findAll();
Assertions.assertEquals(3, allBooks.size());
Long bookId = allBooks.get(0).getId();
Book book = bookReadOnlyRepository.findById(bookId).orElseThrow(NoSuchElementException::new);
Assertions.assertNotNull(book);
}
为了在读回书之前将书保存到数据库中,我们创建了一个BookRepository,该书在测试范围内扩展了CrudRepository。在主项目范围中不需要此存储库,但此存储对于该测试是必需的。
public interface BookRepository
extends BookReadOnlyRepository, CrudRepository {}
我们能够测试所有四种只读方法,并且现在可以将ReadOnlyRepository接口重用于其他实体。
总结
我们学习了如何扩展Spring Data的Repository接口,以创建可重用的只读存储库。之后,我们将其绑定到一个简单的Book实体,并编写了一个测试,证明了其功能符合我们的预期。
共有 0 条评论