閱讀934 返回首頁    go 阿裏雲 go 技術社區[雲棲]


使用Spring Data 倉庫工作 4.1-4.3

Spring Data 倉庫抽象的目標是為了明顯減少為了各種持久存儲的來實現的數據訪問層的樣板代碼量。

Spring Data存儲庫文檔和你的模塊
本章解釋了Spring Data 存儲庫的核心觀念,以及接口。本章的信息來自Spring Data公共模塊。它使用了Java Persistence API(JPA)中的配置以及代碼實例。將命名空間聲明和要擴展的類型擴展為你將會使用的模塊的等效項。命名空間引用包含了所有被Spring Data模塊支持的存儲庫API的XML配置,存儲庫查詢關鍵字包含了常用的存儲庫抽象所支持的查詢方法關鍵字。對於模塊特定特性的詳細信息,參閱文檔中講述該模塊的章節。

4.1 核心觀點

在Spring Data 抽象中中心接口就是Repository(沒有多大意外)。它使用域類來管理以及將域類的id類型作為類型參數。這個接口主要作為標記的接口來捕捉工作的類型並且幫助你去發現被擴展的接口。CrudRepository 提供了複雜的CRUD功能給以及被管理的實體類。

public interface CrudRepository<T, ID extends Serializable>extends Repository<T, ID> {

<S extends T> S save(S entity); //1

T findOne(ID primaryKey);       //2

Iterable<T> findAll();          //3

Long count();                   //4

void delete(T entity);          //5

boolean exists(ID primaryKey);  //6

// … more functionality omitted.
}

1.保存實體。
2.返回給定標識符的實體。
3.返回全部實體。
4.返回實體的個數。
5.刪除給定的實體。
6.表明給定ID的實體是否存在。

我們仍然提供技術指定的持久層抽象,比如JpaRepository 或者 MongoRepository。這些接口擴展了CrudRepository 並且比起通用的持久層與技術無關的接口比如CrudRepository來說暴露了另外的底層的持久層技術功能。

在CrudRepository上層有一個PagingAndSortingRepository抽象添加了另外的方法來輕鬆使用分頁的方式訪問實體。

public interface PagingAndSortingRepository<T, ID extends Serializable>
extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}

訪問第二頁的頁麵大小為20的User,你可以這麼處理:

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));

除了查詢方法,查詢導出計數和刪除查詢都是可用的。
例子3:查詢導出計數

public interface UserRepository extends CrudRepository<User, Long> {
Long countByLastname(String lastname);
}

例子4 查詢刪除

public interface UserRepository extends CrudRepository<User, Long> {
Long deleteByLastname(String lastname);
List<User> removeByLastname(String lastname);
}

4.2 查詢方法

標準的CRUD功能性存儲庫通常在底層的數據庫裏有查詢。在SpringData 中聲明這些查詢通常有四步:
1.聲明一個擴展了Respository或者它的子接口並且設置了它的域類和Id類型的接口。

interface PersonRepository extends Repository<Person, Long> { … }  

2.聲明這個接口的查詢方法

interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLastname(String lastname);
}

3.設置Spring為這些接口創建代理實例.可以用JavaConfig

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
class Config {}

或者使用XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="https://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/data/jpa
https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositories base-package="com.acme.repositories"/>
</beans>

這個例子中使用的是JPA的命名空間。如果你要使用其他的存儲庫抽象,你需要替換jpa為合適的存儲模塊的命名空間聲明比如mongodb。
同時,注意JavaConfig變量不會顯示配置包而是默認使用注釋類的包。使用數據存儲特定的存儲庫@Enable…-注解的basePackage屬性來自定義要掃描的包。
4.注入存儲庫的實例並且使用它:

public class SomeClient {
    @Autowired
    private PersonRepository repository;
    public void doSomething() {
    List<Person> persons = repository.findByLastname("Matthews");
    }
}

接下來的章節解釋了每一步的細節。

4.3 定義存儲庫接口

作為第一步你定義一個域指定類存儲庫接口。這個接口必須擴展自Repository,並鍵入到域類和ID類型。如果你想要暴露CRUD方法給域類型可以擴展CrudRepository而不是Repository。
###4.3.1 微調存儲庫的定義
一般來說你的存儲庫接口會擴展自Repository,CrudRepository或者PagingAndSortingRepository。但是如果你不想要擴展Spring Data的接口,你可以通過使用@RepositoryDefinition注入你自己的存儲庫接口。擴展CrudRepository 暴露了一係列完整的方法來操控你的實體。如果你偏向於對與暴露的方法有選擇性,簡單的從CrudRepository複製對應的方法到你的域存儲庫中。

這個允許你在提供的Spring Data 存儲庫的功能之上定義你自己的抽象

例子5.選擇性暴露CRUD方法

@NoRepositoryBean
interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
    T findOne(ID id);
    T save(T entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
User findByEmailAddress(EmailAddress emailAddress);
}

在第一步你定義了一個基本的接口給你全部的域存儲同時暴露了findOne()和Save()兩個方法。這些方法將會被路由到你選擇的由SpringData提供的存儲的基礎的存儲庫實現,比如如果是JPA 就是SimpleJpaRepository,因為他們滿足在CrudRepository中的方法標簽。所以UserRepository現在可以存儲用戶,根據id來查找指定用戶,或者觸發一個按照他們的郵件地址的查詢。

注意中間的存儲庫接口由@NoRepositoryBean注解表示。確保你添加了這個注解給所有的存儲庫接口,這樣Spring Data不會在運行時創建實例。

4.4.2 對多個Spring Data模塊使用存儲庫

在應用中使用一個唯一的Spring Data 模塊可以使事情簡單,因此所有在定義範圍內的存儲庫接口都被綁定到Spring Data 模塊。有時應用要求使用一個以上的Spring Data 模塊。在這個情況下,要求存儲庫的定義可以分辨不同的存儲層技術。由於可以檢測到多個存儲庫工廠在類路徑中,Spring Data 使用嚴格的存儲庫配置模式。嚴格的配置需要存儲庫的細節或者域類來決定Spring Data 模塊綁定一個存儲庫的定義:
1.如果存儲庫定義擴展指定模塊的存儲庫,那麼它是一個合格的對於特定的Spring Data 模塊的候選者。
2.如果域類是由模塊特定的類型注解來注解的,那麼它是一個合格的對於特定的Spring Data 模塊的候選者。Spring Data 模塊接受第三方的注解(比如JPA的 @Entity)或者提供自己的注解比如@Document用於Spring Data MongoDB/Spring Data Elasticsearch。
例子6 使用指定模塊的接口定義的存儲庫

interface MyRepository extends JpaRepository<User, Long> { }

@NoRepositoryBean
interface MyBaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
…
}

interface UserRepository extends MyBaseRepository<User, Long> {
 …
}

MyRepository和UserRepository擴展JpaRepository在他們的類型層級中。他們是Spring Data JPA模塊的合法的候選人。
例子7 使用通用接口定義的存儲庫

interface AmbiguousRepository extends Repository<User, Long> {
…
}

@NoRepositoryBean
interface MyBaseRepository<T, ID extends     Serializable> extends CrudRepository<T, ID> {
 …
}

interface AmbiguousUserRepository extends MyBaseRepository<User, Long> {
…
}

AmbiguousRepository和AmbiguousUserRepository隻擴展了Repository和CrudRepository在它們的類型層級中。雖然這是完全正確的使用一個唯一的Spring Data模塊,多模塊沒法辨識這個存儲庫應該綁定哪一個特定的Spring Data。
例子8 使用注解域類定義的存儲庫

interface PersonRepository extends Repository<Person, Long> {
…
}
@Entity
public class Person {
 …
}
interface UserRepository extends Repository<User, Long> {
 …
}
@Document
public class User {
…
}

由於PersonRepository 引用使用JPA注解@Entity注解的Person,這個存儲庫清楚的屬於Spring Data JPA。UserRepository使用Spring Data MongoDB的@Document注解的User類。
例子9 使用注解和域類混合的存儲庫定義

interface JpaPersonRepository extends Repository<Person, Long> {
 …
}
interface MongoDBPersonRepository extends Repository<Person, Long> {
…
}
@Entity
@Document
public class Person {
…
}

這個例子展示一個域類使用了JPA和MongoDb的注解。它定義了兩個存儲庫,JpaPersonRepository和MongoDBPersonRepository.一個給JPA,一個給MongoDB使用。Spring Data 不能分辨出存儲庫,將會導致未定義的行為。
存儲庫類型細節分辨域類注解用於嚴格的存儲庫配置對一個Spring Data 模塊來區分存儲庫候選人。在相同的域類型中使用多個持久層技術注解可以重用域類型來訪問多持久層技術,但是Spring Data 不再可以決定一個特定的模塊綁定到存儲庫。
最後一個方法來區分存儲庫是作用域基礎包。基礎包定義了開始點用來掃描哪些存儲庫接口在合適的包中實現了存儲庫的定義。默認的注解驅動配置使用了配置類的包。這個使用XML基礎配置的基礎包是強製性的。
例子10 基礎包的注解驅動配置

@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
interface Configuration { }

 轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 11:31:54

  上一篇:go  《Spring Data 官方文檔翻譯》3. 其他幫助資源
  下一篇:go  《Spring Data 官方文檔》5.6 保存, 更新, 以及刪除數據行