主要譯自:
https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#repositories
https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.repositories
8. Working with Spring Data Repositories
本章解釋了Spring Data存儲庫的核心概念和接口。
一言蔽之,Spring Data repository抽象的目標就是——減少重複的模板代碼。
8.1. Core concepts
Spring Data repository抽象(abstraction)的中心接口是repository。它將域類(domain class)以及域類的ID類型作爲類型參數(type arguments)進行管理。此接口主要用作標記接口,用於捕獲要使用的類型,並幫助您發現繼承(extend)此類型的接口。Crudepository接口爲正在管理的實體類(the entity class)提供複雜的CRUD功能。
public interface CrudRepository<T, ID> extends Repository<T, ID> { <S extends T> S save(S entity); Optional<T> findById(ID primaryKey); Iterable<T> findAll(); long count(); void delete(T entity); boolean existsById(ID primaryKey); // … more functionality omitted. }
從上往下的註釋:
- 保存給定的實體。(對應<S extends T> S save(S entity);)
- 返回由給定ID標識的實體。
- 返回所有實體。
- 返回實體數。
- 刪除給定的實體。
- 指示具有給定ID的實體是否存在。
我們還提供特定於持久性技術的抽象,如JpaRepository或MongoRepository。這些接口擴展(extend)了Crudepository,並公開了底層持久性技術的功能,以及與持久性技術無關的通用接口,如CrudRepository。
在CrudRepository之上,還有一個PagingAndSortingRepository抽象,它添加了其他方法,以簡化對實體的分頁訪問:(見原文)
除了查詢方法外,還可以對計數和刪除查詢進行查詢派生(query derivation)。下表顯示了派生(derived )計數查詢的接口定義:
interface UserRepository extends CrudRepository<User, Long> { long countByLastname(String lastname); }
8.2. Query Methods
標準CRUD功能存儲庫通常對底層數據存儲進行查詢。使用Spring數據,聲明這些查詢將變成一個四步過程:
①聲明一個接口繼承Repository或其子接口之一,並將其鍵入應處理的域類(domain class)和ID類型,如以下示例所示:
interface PersonRepository extends Repository<Person, Long> { … }
②在接口上聲明查詢方法。
interface PersonRepository extends Repository<Person, Long> { List<Person> findByLastname(String lastname); }
③設置Spring,使用JavaConfig或XML配置爲這些接口創建代理實例(proxy instances)。(詳見文檔)
④注入存儲庫實例(the repository instance)並使用它,如下例所示:
class SomeClient { private final PersonRepository repository; SomeClient(PersonRepository repository) { this.repository = repository; } void doSomething() { List<Person> persons = repository.findByLastname("Matthews"); } }
9. JDBC Repositories
本章指出了JDBC存儲庫支持的特點。這建立在“Working with Spring Data Repositories”中介紹的核心存儲庫支持的基礎上。你應該對這裏解釋的基本概念有很好的理解。
9.1. Why Spring Data JDBC?
Java世界中關係數據庫的主要持久化API當然是JPA,它有自己的Spring數據模塊。爲什麼還有另一個?
JPA做了很多事情來幫助開發者。除此之外,它還跟蹤實體的變化。它爲您提供了惰性加載。它允許您將大量對象構造映射到同樣廣泛的數據庫設計。
這很好,讓很多事情變得非常簡單。請看一個基本的JPA教程。但對於JPA爲什麼要做某件事,人們往往會感到困惑。而且,在JPA中,概念上非常簡單的事情變得相當困難。
Spring Data JDBC的目標是在概念上更加簡單,包括以下設計決策:
- 如果加載實體,SQL語句就會運行。完成後,就有了一個完全加載的實體。沒有進行延遲加載或緩存。
- 如果保存一個實體,它將被保存。如果你不這樣做,它就不會。沒有骯髒的跟蹤和會話。
- 關於如何將實體映射到表,有一個簡單的模型。它可能只適用於相當簡單的情況。如果你不喜歡這樣,你應該編寫自己的策略。Spring Data JDBC對使用註釋定製策略的支持非常有限。
9.2. Domain Driven Design and Relational Databases.
所有Spring數據模塊都受到域驅動設計(DDD)中“存儲庫”、“聚合”和“聚合根”概念的啓發。這些對於Spring Data JDBC可能更重要,因爲它們在某種程度上與處理關係數據庫時的常規做法相反。
聚合(aggregate)是一組實體,保證在對其進行原子更改時保持一致。一個典型的例子是帶有OrderItems的Order。Order上的屬性(例如,numberOfItems與OrderItems的實際數量一致)在進行更改時保持一致。
聚合之間的引用(References)並不保證一直都是一致的。但他們保證最終會是一致的。
每個聚合有且僅有一個聚合根(aggregate root),它是聚合的一個實體。僅通過聚合根上的方法對聚合進行操作。這些是前面提到的原子變化。
存儲庫(repository)是持久化存儲的抽象,它看起來像是某個類型的所有聚合的集合。對於一般的Spring Data,這意味着您希望每個聚合根都有一個Repository。此外,對於Spring Data JDBC,這意味着從聚合根可訪問的所有實體都被認爲是該聚合根的一部分。Spring Data JDBC假設只有聚合具有存儲聚合的非根實體的表的外鍵,並且沒有其他實體指向非根實體。(????)
在當前的實現中,Spring Data JDBC刪除並重新創建從聚合根引用的實體。
您可以使用與您的工作和設計數據庫的風格相匹配的實現來覆蓋存儲庫方法。
9.3. Getting Started
引導設置工作環境的一種簡單方法是在STS或Spring Initializer中創建一個基於Spring的項目。
首先,您需要設置一個正在運行的數據庫服務器。有關如何爲JDBC訪問配置數據庫的信息,請參閱供應商文檔。
9.4. Examples Repository
https://github.com/spring-projects/spring-data-examples
9.5. Annotation-based Configuration
Spring Data JDBC存儲庫支持可以通過Java配置的註釋激活,如下例所示:
@Configuration @EnableJdbcRepositories // 爲從Repository派生的接口創建實現 class ApplicationConfig extends AbstractJdbcConfiguration { // 提供Spring Data JDBC所需的各種默認bean @Bean DataSource dataSource() { // 創建連接到數據庫的數據源。 // 這是以下兩種bean方法所必需的。 EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.HSQL).build(); } @Bean NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { // 創建Spring Data JDBC用於訪問數據庫的NamedParameterJDBC操作 return new NamedParameterJdbcTemplate(dataSource); } @Bean TransactionManager transactionManager(DataSource dataSource) { // Spring Data JDBC利用Spring JDBC提供的事務管理。 return new DataSourceTransactionManager(dataSource); } }
前面示例中的配置類通過使用spring-jdbc的EmbeddedDatabaseBuilder API建立嵌入式HSQL數據庫。然後使用DataSource設置NamedParameterJdbcOperations和TransactionManager。最後,我們使用@EnableJdbcRepositories激活Spring Data JDBC存儲庫。如果沒有配置基本包,它將使用配置類所在的包。擴展AbstractJdbcConfiguration可確保註冊各種bean。覆蓋其方法可用於自定義設置(見下文)。
使用Spring Boot可以進一步簡化此配置。在Spring Boot中,一旦spring-boot-starter-data-jdbc包含在依賴項中,數據源就足夠了。其他一切都由Spring Boot完成。
在這個設置中,可能需要定製一些東西。