使用 Spring Data Repositories(下)

Adobe國際認證發表於2021-09-24

原標題:Spring認證|使用 Spring Data Repositories(下)來源:( #spring認證#Spring中國教育管理中心)

4.5.2. Java配置

使用 Spring Data Repositories(下)

您還可以透過@Enable$Repositories在 Java 配置類上使用特定於商店的註釋來觸發儲存庫基礎結構。有關 Spring 容器的基於 Java 的配置的介紹,請參閱Spring 參考文件中的 JavaConfig。

啟用 Spring Data 儲存庫的示例配置類似於以下內容:

示例 29. 基於註解的儲存庫配置示例

@Configuration

@EnableJpaRepositories("com.acme.repositories")

class ApplicationConfiguration {

@Bean

EntityManagerFactory entityManagerFactory() {

// …

}

}

前面的示例使用特定於 JPA 的註釋,您可以根據實際使用的商店模組更改該註釋。這同樣適用於EntityManagerFactorybean的定義。請參閱涵蓋商店特定配置的部分。

4.5.3. 獨立使用

您還可以在 Spring 容器之外使用儲存庫基礎設施——例如,在 CDI 環境中。您的類路徑中仍然需要一些 Spring 庫,但通常,您也可以透過程式設計方式設定儲存庫。提供儲存庫支援的 Spring Data 模組附帶了RepositoryFactory您可以使用的特定於永續性技術的技術,如下所示:

示例 30. 儲存庫工廠的獨立使用

RepositoryFactorySupport factory = … // Instantiate factory here

UserRepository repository = factory.getRepository(UserRepository.class);

4.6. Spring Data Repositories 的自定義實現

Spring Data 提供了各種選項來建立只需很少編碼的查詢方法。但是當這些選項不符合您的需求時,您還可以為儲存庫方法提供您自己的自定義實現。本節介紹如何做到這一點。

4.6.1. 自定義單個儲存庫

要使用自定義功能豐富儲存庫,您必須首先定義片段介面和自定義功能的實現,如下所示:

示例 31. 自定義儲存庫功能的介面

interface CustomizedUserRepository {

void someCustomMethod(User user);

}

示例 32. 自定義儲存庫功能的實現

class CustomizedUserRepositoryImpl implements CustomizedUserRepository {

public void someCustomMethod(User user) {

// Your custom implementation

}

}

與片段介面對應的類名中最重要的部分是Impl字尾。

實現本身不依賴於Spring Data,可以是一個普通的Spring bean。因此,你可以使用標準的依賴注入行為來注入對其他bean(例如a JdbcTemplate)的引用,參與方面等等。

然後你可以讓你的repository介面擴充套件fragment介面,如下:

示例 33. 對儲存庫介面的更改

interface UserRepository extends CrudRepository, CustomizedUserRepository {

// Declare query methods here

}

使用您的儲存庫介面擴充套件片段介面結合了 CRUD 和自定義功能,並使其可供客戶端使用。

Spring Data 儲存庫是透過使用形成儲存庫組合的片段來實現的。片段是基礎儲存庫、功能方面(例如QueryDsl)和自定義介面及其實現。每次向儲存庫介面新增介面時,您都可以透過新增片段來增強組合。每個 Spring Data 模組都提供基本儲存庫和儲存庫方面的實現。

以下示例顯示了自定義介面及其實現:

示例 34. 片段及其實現

interface HumanRepository {

void someHumanMethod(User user);

}

class HumanRepositoryImpl implements HumanRepository {

public void someHumanMethod(User user) {

// Your custom implementation

}

}

interface ContactRepository {

void someContactMethod(User user);

User anotherContactMethod(User user);

}

class ContactRepositoryImpl implements ContactRepository {

public void someContactMethod(User user) {

// Your custom implementation

}

public User anotherContactMethod(User user) {

// Your custom implementation

}

}

使用 Spring Data Repositories(下)

以下示例顯示了擴充套件的自定義儲存庫的介面CrudRepository:

示例 35. 對儲存庫介面的更改

interface UserRepository extends CrudRepository, HumanRepository, ContactRepository {

// Declare query methods here

}

儲存庫可能由按宣告順序匯入的多個自定義實現組成。自定義實現比基本實現和儲存庫方面具有更高的優先順序。如果兩個片段貢獻相同的方法簽名,則此排序允許您覆蓋基本儲存庫和方面方法並解決歧義。儲存庫片段不限於在單個儲存庫介面中使用。多個儲存庫可以使用片段介面,讓您可以在不同的儲存庫中重用自定義。

以下示例顯示了儲存庫片段及其實現:

示例 36. 片段覆蓋 save(…)

interface CustomizedSave {

S save(S entity);

}

class CustomizedSaveImpl implements CustomizedSave {

public S save(S entity) {

// Your custom implementation

}

}

以下示例顯示了使用上述儲存庫片段的儲存庫:

示例 37. 自定義儲存庫介面

interface UserRepository extends CrudRepository, CustomizedSave {

}

interface PersonRepository extends CrudRepository, CustomizedSave {

}

配置

如果您使用名稱空間配置,儲存庫基礎結構會嘗試透過掃描它在其中找到儲存庫的包下的類來自動檢測自定義實現片段。這些類需要遵循將名稱空間元素的repository-impl-postfix屬性附加到片段介面名稱的命名約定。此字尾預設為Impl. 以下示例顯示了一個使用預設字尾的儲存庫和一個為字尾設定自定義值的儲存庫:

示例 38. 配置示例

前面示例中的第一個配置嘗試查詢一個稱為
com.acme.repository.CustomizedUserRepositoryImpl作為自定義儲存庫實現的類。第二個示例嘗試查詢com.acme.repository.CustomizedUserRepositoryMyPostfix.

解決歧義

如果在不同的包中找到多個具有匹配類名的實現,Spring Data 使用 bean 名稱來標識使用哪個。

鑑於CustomizedUserRepository前面顯示的以下兩個自定義實現,使用第一個實現。它的 bean 名稱是
customizedUserRepositoryImpl,它與片段 interface( CustomizedUserRepository) 加上字尾的名稱相匹配Impl。

示例 39. 解決不明確的實現

package com.acme.impl.one;

class CustomizedUserRepositoryImpl implements CustomizedUserRepository {

// Your custom implementation

}

package com.acme.impl.two;

@Component("specialCustomImpl")

class CustomizedUserRepositoryImpl implements CustomizedUserRepository {

// Your custom implementation

}

使用 Spring Data Repositories(下)

如果您使用 註釋UserRepository介面@Component("specialCustom"),那麼 bean 名稱加號Impl與 中為儲存庫實現定義的名稱相匹配com.acme.impl.two,並使用它代替第一個名稱。

手動接線

如果您的自定義實現僅使用基於註解的配置和自動裝配,則前面顯示的方法效果很好,因為它被視為任何其他 Spring bean。如果您的實現片段 bean 需要特殊連線,您可以根據上一節中描述的約定宣告 bean 併為其命名。然後,基礎設施透過名稱引用手動定義的 bean 定義,而不是自己建立一個。以下示例顯示瞭如何手動連線自定義實現:

示例 40. 自定義實現的手動接線

4.6.2. 自定義基礎儲存庫

當您想要自定義基本儲存庫行為以便影響所有儲存庫時,上一節中描述的方法需要自定義每個儲存庫介面。要改為更改所有儲存庫的行為,您可以建立一個擴充套件永續性技術特定儲存庫基類的實現。然後,此類充當儲存庫代理的自定義基類,如以下示例所示:

示例 41.自定義儲存庫基類

class MyRepositoryImpl

extends SimpleJpaRepository {

private final EntityManager entityManager;

MyRepositoryImpl(JpaEntityInformation entityInformation,

EntityManager entityManager) {

super(entityInformation, entityManager);

// Keep the EntityManager around to used from the newly introduced methods.

this.entityManager = entityManager;

}

@Transactional

public S save(S entity) {

// implementation goes here

}

}

使用 Spring Data Repositories(下)

該類需要具有特定於商店的儲存庫工廠實現使用的超類的建構函式。如果儲存庫基類有多個建構函式,則覆蓋一個EntityInformation加上儲存特定基礎結構物件(例如一個EntityManager或一個模板類)的建構函式。

最後一步是讓 Spring Data 基礎設施知道定製的儲存庫基類。在 Java 配置中,您可以透過使用註解的repositoryBaseClass屬性來實現@Enable$Repositories,如下例所示:

示例 42. 使用 JavaConfig 配置自定義儲存庫基類

@Configuration

@EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)

class ApplicationConfiguration { … }

XML 名稱空間中提供了相應的屬性,如以下示例所示:

示例 43. 使用 XML 配置自定義儲存庫基類

base-class="….MyRepositoryImpl" />

4.7. 從聚合根釋出事件

儲存庫管理的實體是聚合根。在域驅動設計應用程式中,這些聚合根通常釋出域事件。Spring Data 提供了一個名為的註釋@DomainEvents,您可以在聚合根的方法上使用該註釋,以使該釋出儘可能簡單,如以下示例所示:

示例 44. 從聚合根公開域事件

class AnAggregateRoot {

@DomainEvents

Collection domainEvents() {

// … return events you want to get published here

}

@AfterDomainEventPublication

void callbackMethod() {

// … potentially clean up domain events list

}

}

使用的方法@DomainEvents可以返回單個事件例項或事件集合。它不能接受任何論據。

釋出所有事件後,我們就有了一個用@
AfterDomainEventPublication. 您可以使用它潛在地清理要釋出的事件列表(以及其他用途)。

該方法被稱為一個Spring資料儲存庫的每一次一個save(…),saveAll(…),delete(…)或deleteAll(…)方法被呼叫。

4.8. Spring 資料擴充套件

本節記錄了一組 Spring Data 擴充套件,這些擴充套件支援在各種上下文中使用 Spring Data。目前,大部分整合都針對 Spring MVC。

4.8.1. Querydsl 擴充套件

Querydsl是一個框架,可以透過其流暢的 API 構建靜態型別的 SQL 類查詢。

幾個 Spring Data 模組透過 提供與 Querydsl 的整合QuerydslPredicateExecutor,如以下示例所示:


45.QuerydslPredicateExecutor 介面

public interface QuerydslPredicateExecutor {

Optional findById(Predicate predicate);

Iterable findAll(Predicate predicate);

long count(Predicate predicate);

boolean exists(Predicate predicate);

// … more functionality omitted.

}

查詢並返回與 匹配的單個實體Predicate。

查詢並返回與 匹配的所有實體Predicate。

返回與 匹配的實體數Predicate。

返回匹配的實體是否Predicate存在。

要使用 Querydsl 支援,請擴充套件QuerydslPredicateExecutor您的儲存庫介面,如以下示例所示:

示例 46. 儲存庫上的 Querydsl 整合

interface UserRepository extends CrudRepository, QuerydslPredicateExecutor {

}

前面的示例允許您使用 QuerydslPredicate例項編寫型別安全的查詢,如以下示例所示:

Predicate predicate = user.firstname.equalsIgnoreCase("dave")

.and(user.lastname.startsWithIgnoreCase("mathews"));

userRepository.findAll(predicate);

4.8.2. 網路支援

支援儲存庫程式設計模型的 Spring Data 模組附帶了各種 Web 支援。Web 相關元件要求 Spring MVC JAR 位於類路徑上。其中一些甚至提供與Spring HATEOAS 的整合。通常,透過使用@
EnableSpringDataWebSupportJavaConfig 配置類中的註釋來啟用整合支援,如以下示例所示:

示例 47.啟用 Spring Data Web 支援

@Configuration

@EnableWebMvc

@EnableSpringDataWebSupport

class WebConfiguration {}

該@
EnableSpringDataWebSupport批註註冊幾個元件。我們將在本節後面討論這些。它還檢測類路徑上的 Spring HATEOAS 併為其註冊整合元件(如果存在)。

或者,如果您使用 XML 配置,請註冊
SpringDataWebConfiguration或HateoasAwareSpringDataWebConfiguration作為 Spring bean,如以下示例所示(對於SpringDataWebConfiguration):

示例 48. 在 XML 中啟用 Spring Data Web 支援

基本網路支援

上一節中顯示的配置註冊了一些基本元件:

A使用DomainClassConverter類讓 Spring MVC 從請求引數或路徑變數解析儲存庫管理的域類的例項。


HandlerMethodArgumentResolver讓 Spring MVC從請求引數解析Pageable和Sort例項的實現。

Jackson Modules用於反/序列化Point和 等型別Distance,或儲存特定型別,具體取決於所使用的 Spring 資料模組。

使用DomainClassConverter類

本DomainClassConverter類讓你在Spring MVC中的控制器方法簽名使用域型別直接使您不必手動透過資源庫查詢的情況下,如下例所示:

示例 49. 在方法簽名中使用域型別的 Spring MVC 控制器

@Controller

@RequestMapping("/users")

class UserController {

@RequestMapping("/")

String showUserForm(@PathVariable("id") User user, Model model) {

model.addAttribute("user", user);

return "userForm";

}

}

該方法User直接接收例項,不需要進一步查詢。可以透過讓 Spring MVCid先將路徑變數轉換為域類的型別,最終透過呼叫findById(…)為域型別註冊的儲存庫例項來訪問例項來解析例項。

目前,儲存庫必須實現CrudRepository才能被發現進行轉換。

用於可分頁和排序的
HandlerMethodArgumentResolvers

的配置片段中,在示出前一節還註冊一個
PageableHandlerMethodArgumentResolver,以及例項SortHandlerMethodArgumentResolver。註冊啟用Pageable並Sort作為有效的控制器方法引數,如以下示例所示:

示例 50.使用 Pageable 作為控制器方法引數

@Controller

@RequestMapping("/users")

class UserController {

private final UserRepository repository;

UserController(UserRepository repository) {

this.repository = repository;

}

@RequestMapping

String showUsers(Model model, Pageable pageable) {

model.addAttribute("users", repository.findAll(pageable));

return "users";

}

}

使用 Spring Data Repositories(下)

使用 Spring Data Repositories(下)

要自定義此行為,請分別註冊一個實現
PageableHandlerMethodArgumentResolverCustomizer介面或SortHandlerMethodArgumentResolverCustomizer介面的 bean 。它的customize()方法被呼叫,讓您更改設定,如以下示例所示:

@Bean SortHandlerMethodArgumentResolverCustomizer sortCustomizer() {

return s -> s.setPropertyDelimiter("");

}

如果設定現有的屬性MethodArgumentResolver不足以滿足您的目的,請擴充套件
SpringDataWebConfiguration或啟用 HATEOAS 的等效項,覆蓋pageableResolver()或sortResolver()方法,並匯入您的自定義配置檔案而不是使用@Enable註釋。

如果您需要從請求中解析多個Pageable或多個Sort例項(例如,對於多個表),您可以使用 Spring 的@Qualifier註解來區分一個和另一個。請求引數必須以 為字首$_。以下示例顯示了生成的方法簽名:

String showUsers(Model model,

@Qualifier("thing1") Pageable first,

@Qualifier("thing2") Pageable second) { … }

您必須填充thing1_page、thing2_page等。

Pageable傳遞給方法的預設值等效於 a PageRequest.of(0, 20),但您可以透過使用引數@PageableDefault上的註釋來自定義它Pageable。

0),但您可以透過使用引數@PageableDefault上的註釋來自定義它Pageable。

內容來源:(Spring中國教育管理中心)

使用 Spring Data Repositories,未完待續.....


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69981720/viewspace-2793558/,如需轉載,請註明出處,否則將追究法律責任。

相關文章