Java 用 Azure Spring Data Cosmos クライアント ライブラリ - バージョン 5.6.0
Azure Spring Data Cosmos は、Spring Data フレームワークに基づいて、SQL API を使用した Azure Cosmos DB の Spring Data サポートを提供します。 Azure Cosmos DB は、開発者が SQL、MongoDB、Cassandra、Graph、Table などのさまざまな標準 API を使用してデータを操作できるようにするグローバル分散型データベース サービスです。
Spring Boot サポート ポリシー
このプロジェクトでは、複数の Spring Boot バージョンがサポートされています。 現在サポートされているバージョンの全一覧については、Spring バージョンのマッピングに関するページを参照してください。
Spring Boot リリースは、何らかの形でサポートまたはリリースされなくなると、"サポート終了" とマークされます。 EOL バージョンを実行している場合は、できるだけ早くアップグレードする必要があります。
"サポート終了" とマークされる前に、バージョンがサポート対象外になる可能性があることに注意してください。 この期間中は、重大なバグやセキュリティの問題に対してのみリリースを想定する必要があります。
Spring Boot のサポート対象バージョンについて詳しくは、Spring Boot のサポート対象バージョンに関するページを参照してください。
Spring Boot バージョンのサポート
Maven ユーザーは、spring-boot-starter-parent
プロジェクトを継承して、依存関係管理セクションを取得し、Spring で依存関係のためにバージョンを管理できるようにします。
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
</parent>
この設定を使用して、独自のプロジェクトでプロパティをオーバーライドすることで、個々の依存関係をオーバーライドすることもできます。 たとえば、別の Spring Data リリース トレインにアップグレードするには、以下を pom.xml に追加します。
<properties>
<spring-data-releasetrain.version>${spring.data.version}</spring-data-releasetrain.version>
</properties>
spring-boot-starter-parent
を使用しない場合でも、次のように scope=import
依存関係を使用して、依存関係管理の利点を引き続き利用できます。
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
どのバージョンの Azure Spring Data Cosmos を使用すべきか
Spring Boot / Spring Cloud バージョンから Azure Spring Data Cosmos バージョンへのマッピング
Spring Boot のバージョン | Spring Cloud のバージョン | Azure Spring Data Cosmos のバージョン |
---|---|---|
3.0.x | 2022.0.x | 5.3.0 以降 |
2.7.x | 2021.0.x | 3.23.0 以降 |
2.6.x | 2021.0.x | 3.15.0 - 3.22.0 |
2.5.x | 2020.0.x | 3.8.0 - 3.14.0 |
2.4.x | 2020.0.x | 3.5.0 - 3.7.0 |
Spring Boot バージョン X を使用しています
プロジェクトで Spring Boot を使用している場合は、上の表から関連する Azure Spring Data Cosmos バージョンを確認できます。 たとえば、 Spring Boot 3.0.x を使用している場合は、 Azure Spring Data Cosmos バージョン 5.3.0 以降を使用する必要があります。
Spring Cloud バージョン Y を使用しています
プロジェクトで Spring Cloud を使用している場合は、上記の表から関連する Azure Spring Data Cosmos バージョンも確認できます。 たとえば、 Spring Cloud 2022.0.x を使用している場合は、 Azure Spring Data Cosmos バージョン 5.3.0 以降を使用する必要があります。
Spring Data バージョンのサポート
このプロジェクトでは、バージョンが spring-data-commons 3.0.x
サポートされています。
上記のセットアップでは、上記のように プロパティを使用して個々の依存関係をオーバーライドすることはできません。 同じ結果を得るには、プロジェクトの dependencyManagement で spring-boot-dependencies
エントリの前にエントリを追加する必要があります。 たとえば、別の Spring Data リリース トレインにアップグレードするには、以下を pom.xml に追加します。
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring.data.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注:${spring.boot.version} と ${spring.data.version} は、プロジェクトで使用する Spring Boot と Spring Data のバージョンに置き換えてください。
作業の開始
パッケージを組み込む
Maven を使用している場合は、以下の依存関係を追加します。
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-spring-data-cosmos</artifactId>
<version>5.6.0</version>
</dependency>
前提条件
- Java Development Kit (JDK) バージョン 8 以降。
- アクティブな Azure アカウントアカウントがない場合、Azure 試用版にサインアップして、最大 10 件の無料 Mobile Apps を入手できます。 お持ちでない場合は、 無料アカウントにサインアップしてください。 または、Azure Cosmos DB Emulator を使用して、開発とテストを行うこともできます。 エミュレーターの https 証明書は自己署名されているため、その証明書を Java の信頼された証明書ストアにインポートする必要 があります。ここで説明します
- (省略可能) ログ記録ファサードの SLF4J。
- (省略可能) SLF4J バインディング を使用して、特定のログ記録フレームワークを SLF4J と関連付けます。
- (省略可能) Maven
SLF4J は、ログ記録を使用する場合にのみ必要です。また、SLF4J API と選択したログ記録の実装をリンクする SLF4J バインディングもダウンロードしてください。 詳細については、SLF4J のユーザー マニュアルを参照してください。
構成クラスを設定する
構成クラスを設定するために、
AbstractCosmosConfiguration
を拡張する必要があります。Azure-spring-data-cosmos では、 と
Max Degree of Parallelism
もサポートされています。Response Diagnostics String
Query Metrics
application.properties でqueryMetricsEnabled
フラグを true に設定して、クエリ メトリクスを有効にします。 フラグの設定に加えて、診断情報をログ記録するために、ResponseDiagnosticsProcessor
を実装します。 並列処理を許可するには、application.properties でフラグを整数に設定maxDegreeOfParallelism
します。値を -1 に設定すると、SDK によって最適な値が決定されます。 application.properties でフラグを整数に設定maxBufferedItemCount
すると、ユーザーは、並列クエリの実行中にバッファーできる項目の最大数を設定できます。0 未満に設定すると、バッファーする項目の数が自動的に決定されます。 注: これを非常に高い値に設定すると、メモリ消費量が多くなる可能性があります。 application.properties でフラグを整数に設定responseContinuationTokenLimitInKb
して、ユーザーがクエリ応答の継続トークンの長さを制限できるようにします。 継続トークンには、必須フィールドと省略可能フィールドの両方が含まれます。 必要なフィールドは、実行が停止された場所から再開するために必要です。 省略可能なフィールドには、行われたが、まだ使用されていないシリアル化されたインデックス検索作業が含まれている場合があります。 これにより、後続の継続で作業をやり直すのが回避され、クエリのパフォーマンスが向上します。 最大継続サイズを 1 KB に設定すると、Azure Cosmos DB サービスは必須フィールドのみをシリアル化します。 2 KB 以降、Azure Cosmos DB サービスは、指定された最大サイズに達するまで収まる限りシリアル化します。nonPointOperationLatencyThresholdInMS
、、requestChargeThresholdInRU
および を設定pointOperationLatencyThresholdInMS
して、payloadSizeThresholdInBytes
これらのしきい値を超えたときにクライアント レベルで診断を有効にします。
@Configuration
@EnableCosmosRepositories
public class AppConfiguration extends AbstractCosmosConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(AppConfiguration.class);
@Value("${azure.cosmos.uri}")
private String uri;
@Value("${azure.cosmos.key}")
private String key;
@Value("${azure.cosmos.secondaryKey}")
private String secondaryKey;
@Value("${azure.cosmos.database}")
private String dbName;
@Value("${azure.cosmos.queryMetricsEnabled}")
private boolean queryMetricsEnabled;
@Value("${azure.cosmos.maxDegreeOfParallelism}")
private int maxDegreeOfParallelism;
@Value("${azure.cosmos.maxBufferedItemCount}")
private int maxBufferedItemCount;
@Value("${azure.cosmos.responseContinuationTokenLimitInKb}")
private int responseContinuationTokenLimitInKb;
@Value("${azure.cosmos.diagnosticsThresholds.pointOperationLatencyThresholdInMS}")
private int pointOperationLatencyThresholdInMS;
@Value("${azure.cosmos.diagnosticsThresholds.nonPointOperationLatencyThresholdInMS}")
private int nonPointOperationLatencyThresholdInMS;
@Value("${azure.cosmos.diagnosticsThresholds.requestChargeThresholdInRU}")
private int requestChargeThresholdInRU;
@Value("${azure.cosmos.diagnosticsThresholds.payloadSizeThresholdInBytes}")
private int payloadSizeThresholdInBytes;
private AzureKeyCredential azureKeyCredential;
@Bean
public CosmosClientBuilder getCosmosClientBuilder() {
this.azureKeyCredential = new AzureKeyCredential(key);
DirectConnectionConfig directConnectionConfig = new DirectConnectionConfig();
GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig();
return new CosmosClientBuilder()
.endpoint(uri)
.credential(azureKeyCredential)
.directMode(directConnectionConfig, gatewayConnectionConfig)
.clientTelemetryConfig(
new CosmosClientTelemetryConfig()
.diagnosticsThresholds(
new CosmosDiagnosticsThresholds()
.setNonPointOperationLatencyThreshold(Duration.ofMillis(nonPointOperationLatencyThresholdInMS))
.setPointOperationLatencyThreshold(Duration.ofMillis(pointOperationLatencyThresholdInMS))
.setPayloadSizeThreshold(payloadSizeThresholdInBytes)
.setRequestChargeThreshold(requestChargeThresholdInRU)
)
.diagnosticsHandler(CosmosDiagnosticsHandler.DEFAULT_LOGGING_HANDLER));
}
@Override
public CosmosConfig cosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(queryMetricsEnabled)
.maxDegreeOfParallelism(maxDegreeOfParallelism)
.maxBufferedItemCount(maxBufferedItemCount)
.responseContinuationTokenLimitInKb(responseContinuationTokenLimitInKb)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
public void switchToSecondaryKey() {
this.azureKeyCredential.update(secondaryKey);
}
@Override
protected String getDatabaseName() {
return "testdb";
}
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
@Override
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
LOGGER.info("Response Diagnostics {}", responseDiagnostics);
}
}
}
構成のカスタマイズ
または またはその両方をカスタマイズDirectConnectionConfig
して Bean にCosmosClientBuilder
提供してカスタマイズできます。、、 をカスタマイズ nonPointOperationLatencyThresholdInMS
CosmosAsyncClient
pointOperationLatencyThresholdInMS
requestChargeThresholdInRU
して、 とpayloadSizeThresholdInBytes
組み合わせたCosmosDiagnosticsHandler
ときに診断ログのしきい値をカスタマイズできます。これにより、 にCosmosClientBuilder
追加されたときに既定のしきい値で診断ログが有効になります。GatewayConnectionConfig
@Bean
public CosmosClientBuilder getCosmosClientBuilder() {
DirectConnectionConfig directConnectionConfig = new DirectConnectionConfig();
GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig();
return new CosmosClientBuilder()
.endpoint(uri)
.directMode(directConnectionConfig, gatewayConnectionConfig)
.clientTelemetryConfig(
new CosmosClientTelemetryConfig()
.diagnosticsThresholds(
new CosmosDiagnosticsThresholds()
.setNonPointOperationLatencyThreshold(Duration.ofMillis(nonPointOperationLatencyThresholdInMS))
.setPointOperationLatencyThreshold(Duration.ofMillis(pointOperationLatencyThresholdInMS))
.setPayloadSizeThreshold(payloadSizeThresholdInBytes)
.setRequestChargeThreshold(requestChargeThresholdInRU)
)
.diagnosticsHandler(CosmosDiagnosticsHandler.DEFAULT_LOGGING_HANDLER));
}
@Override
public CosmosConfig cosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(queryMetricsEnabled)
.maxDegreeOfParallelism(maxDegreeOfParallelism)
.maxBufferedItemCount(maxBufferedItemCount)
.responseContinuationTokenLimitInKb(responseContinuationTokenLimitInKb)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
既定では、@EnableCosmosRepositories
は現在のパッケージをスキャンして、Spring Data のいずれかのリポジトリ インターフェイスを拡張するインターフェイスを探します。
プロジェクト レイアウトに複数のプロジェクトが含まれている場合は、それを使用して、@EnableCosmosRepositories(basePackageClass=UserRepository.class)
によって別のルート パッケージをスキャンするように構成クラスに注釈を付けます。
JavaAgent を使用して Insights をAzure アプリケーションするためのログ記録診断を有効にする
診断を有効にするには、次のようなアプリケーションで JavaAgent を渡します。 これにより、既定のしきい値を使用したログ記録が有効になります。 '-javaagent' は、'-jar' の前に渡す必要があります。
java -javaagent:"<path-to-applicationinsights-agent-jar>" -jar <myapp.jar>
データベース プロビジョニングスループットの使用
Cosmos では、 コンテナー と データベース の両方でプロビジョニングされたスループットがサポートされます。 既定では、spring-data-cosmos は作成された各コンテナーのスループットをプロビジョニングします。 コンテナー間でスループットを共有する場合は、CosmosConfig を使用してデータベースプロビジョニングスループットを有効にすることができます。
@Override
public CosmosConfig cosmosConfig() {
int autoscale = false;
int initialRequestUnits = 400;
return CosmosConfig.builder()
.enableDatabaseThroughput(autoscale, initialRequestUnits)
.build();
}
エンティティを定義する
単純なエンティティを Azure Cosmos DB の項目として定義します。
エンティティを定義するには、
@Container
注釈を追加し、コンテナー名、要求ユニット (RU)、有効期限、自動作成コンテナーなど、コンテナーに関連するプロパティを指定します。コンテナーは、そのようにしたくない場合を除き、自動的に作成されます。 コンテナーの自動作成を無効にするには、
@Container
注釈でautoCreateContainer
を false に設定します。注: 既定では、新しく作成されたコンテナーに割り当てられる要求ユニットは 400 です。 SDK によって作成されたコンテナーの要求ユニットをカスタマイズするには、別の RU 値を指定します (最小 RU 値は 400)。
@Container(containerName = "myContainer", ru = "400")
public class User {
private String id;
private String firstName;
@PartitionKey
private String lastName;
public User() {
// If you do not want to create a default constructor,
// use annotation @JsonCreator and @JsonProperty in the full args constructor
}
public User(String id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format("User: %s %s, %s", firstName, lastName, id);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
id
フィールドは、Azure Cosmos DB の項目 ID として使用されます。 itemid
などのfirstName
別のフィールドを使用する場合は、そのフィールドに注釈を付@Id
けるだけです。注釈
@Container(containerName="myContainer")
は、Azure Cosmos DB 内のコンテナー名を指定します。lastName
フィールドの注釈@PartitionKey
は、このフィールドを Azure Cosmos DB のパーティション キーとして指定します。
自動スケーリングのスループットを利用したコンテナーの作成
- 注釈
autoScale
フィールドを true に設定すると、自動スケーリングのスループットを利用してコンテナーが作成されることが指定されます。 既定値は false です。これは、コンテナーが手動スループットで作成されることを意味します。 - 自動スケーリングのスループットの詳細については、こちらをご覧ください。
@Container(containerName = "myContainer", autoScale = true, ru = "4000")
public class UserSample {
@Id
private String emailAddress;
}
入れ子になったパーティション キーのサポート
- Azure Spring Data Cosmos では、入れ子になったパーティション キーがサポートされています。 入れ子になったパーティション キーを追加するには、
@Container
注釈でpartitionKeyPath
フィールドを使用します。 partitionKeyPath
は、入れ子になったパーティション キーのパスをサポートする場合にのみ使用してください。 一般的なパーティション キーのサポートでは、@PartitionKey
注釈を使用します。- 特に指定がない限り、既定では、
@PartitionKey
注釈が優先されます。 - 次の例は、入れ子になったパーティション キーの機能を適切に使用する方法を示しています。
@Container(containerName = "nested-partition-key", partitionKeyPath = "/nestedEntitySample/nestedPartitionKey")
public class NestedPartitionKeyEntitySample {
private NestedEntitySample nestedEntitySample;
}
public class NestedEntitySample {
private String nestedPartitionKey;
}
リポジトリを作成する
Spring Data リポジトリのサポートを提供する CosmosRepository インターフェイスを拡張します。
@Repository
public interface UserRepository extends CosmosRepository<User, String> {
Iterable<User> findByFirstName(String firstName);
long countByFirstName(String firstName);
User findOne(String id, String lastName);
}
findByFirstName
メソッドはカスタムのクエリ メソッドであり、firstName ごとに項目を検索します。
クエリ プランのキャッシュ
パーティション キーを含むパーティションまたは注釈付きクエリのような findByFirstName(String firstName)
firstName
Spring リポジトリ クエリ API では、クエリ プランのキャッシュが原因でクエリの実行時間が短縮されます。 現在、クエリ プランのキャッシュは、1 つのパーティションを対象とするクエリ メソッドでのみサポートされています。
QueryAnnotation: リポジトリでの注釈付きクエリの使用
Azure Spring Data Cosmos では、リポジトリでの @Query
を使用した注釈付きクエリの指定がサポートされます。
- 同期 CosmosRepository での注釈付きクエリの例を次に示します。
public interface AnnotatedQueriesUserRepositoryCodeSnippet extends CosmosRepository<User, String> {
@Query("select * from c where c.firstName = @firstName and c.lastName = @lastName")
List<User> getUsersByFirstNameAndLastName(@Param("firstName") String firstName, @Param("lastName") String lastName);
@Query("select * from c offset @offset limit @limit")
List<User> getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit);
@Query("select value count(1) from c where c.firstName = @firstName")
long getNumberOfUsersWithFirstName(@Param("firstName") String firstName);
}
- ReactiveCosmosRepository での注釈付きクエリの例を次に示します。
public interface AnnotatedQueriesUserReactiveRepositoryCodeSnippet extends ReactiveCosmosRepository<User, String> {
@Query("select * from c where c.firstName = @firstName and c.lastName = @lastName")
Flux<User> getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName);
@Query("select * from c offset @offset limit @limit")
Flux<User> getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit);
@Query("select count(c.id) as num_ids, c.lastName from c group by c.lastName")
Flux<ObjectNode> getCoursesGroupByDepartment();
@Query("select value count(1) from c where c.lastName = @lastName")
Mono<Long> getNumberOfUsersWithLastName(@Param("lastName") String lastName);
}
注釈で指定されているクエリは、Cosmos クエリと同じです。 Cosmos での SQL クエリの詳細については、次の記事を参照してください。
- [Sql API クエリ はじめに] sql_queries_getting_started
- [Sql API クエリのチュートリアル] sql_queries_in_cosmos
アプリケーション クラスを作成する
ここでは、すべてのコンポーネントを含むアプリケーション クラスを作成します。
@SpringBootApplication
public class SampleApplication implements CommandLineRunner {
@Autowired
private UserRepository repository;
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
public void run(String... var1) {
final User testUser = new User("testId", "testFirstName", "testLastName");
repository.deleteAll();
repository.save(testUser);
// to find by Id, please specify partition key value if collection is partitioned
final User result = repository.findOne(testUser.getId(), testUser.getLastName());
// Switch to secondary key
UserRepositoryConfiguration bean =
applicationContext.getBean(UserRepositoryConfiguration.class);
bean.switchToSecondaryKey();
// Now repository will use secondary key
repository.save(testUser);
}
}
- Autowire UserRepository インターフェイス。これは、保存、削除、検索などの操作を実行します。
- Spring Data Azure Cosmos DB は、
CosmosTemplate
およびReactiveCosmosTemplate
を使用して、find および save メソッドの背後でクエリを実行します。 ご自身でテンプレートを使用して、より複雑なクエリを実行できます。
主要な概念
CrudRepository および ReactiveCrudRepository
- Azure Spring Data Cosmos では、次の基本的な CRUD 機能を提供する ReactiveCrudRepository および CrudRepository がサポートされています。
- [保存]
- findAll
- findOne by Id
- deleteAll
- ID で削除する
- エンティティの削除
Spring Data の注釈
Spring Data の @Id 注釈
ドメイン クラスのフィールドを Azure Cosmos DB 項目の id
フィールドにマップするには、2 つの方法があります。
- ドメイン クラスのフィールドに
@Id
の注釈を付けます。このフィールドは Cosmos DB の項目id
にマップされます。 - このフィールドの名前を
id
に設定します。このフィールドは、Azure Cosmos DB の項目id
にマップされます。
ID 自動生成
- @GeneratedValue 注釈を使用した文字列型 UUID の自動生成をサポートします。 文字列型 ID を持つエンティティの id フィールドに 注釈を付
@GeneratedValue
けて、挿入前にランダム UUID を自動的に生成できます。
public class GeneratedIdEntity {
@Id
@GeneratedValue
private String id;
}
SpEL 式とカスタム コンテナー名。
- 既定では、コンテナー名はユーザー ドメイン クラスのクラス名になります。 これをカスタマイズするには、
@Container(containerName="myCustomContainerName")
注釈をドメイン クラスに追加します。 コンテナー フィールドでは、プログラムまたは構成プロパティを使用してコンテナー名を指定するために、SpEL 式 (例:container = "${dynamic.container.name}"
またはcontainer = "#{@someBean.getContainerName()}"
) もサポートされます。 - SpEL 式が正常に機能するためには、Spring Application クラスの上に
@DependsOn("expressionResolver")
を追加する必要があります。
@SpringBootApplication
@DependsOn("expressionResolver")
public class SampleApplication {
}
インデックス作成ポリシー
- 既定では、IndexingPolicy は Azure Portal Service によって設定されます。 これをカスタマイズするには、注釈
@CosmosIndexingPolicy
をドメイン クラスに追加します。 この注釈には、カスタマイズする 5 つの属性があります。次を参照してください。
// Indicate if indexing policy use automatic or not
// Default value is true
boolean automatic() default Constants.DEFAULT_INDEXING_POLICY_AUTOMATIC;
// Indexing policy mode, option Consistent.
IndexingMode mode() default IndexingMode.CONSISTENT;
// Included paths for indexing
String[] includePaths() default {};
// Excluded paths for indexing
String[] excludePaths() default {};
一意のキー ポリシー
- Azure Spring Data Cosmos では、ドメイン クラスに注釈
@CosmosUniqueKeyPolicy
を追加してコンテナーの設定UniqueKeyPolicy
をサポートしています。 この注釈には、次の属性があります。
@Container
@CosmosUniqueKeyPolicy(uniqueKeys = {
@CosmosUniqueKey(paths = {"/lastName", "/zipCode"}),
@CosmosUniqueKey(paths = {"/city"})
})
public class CosmosUniqueKeyPolicyCodeSnippet {
@Id
String id;
@PartitionKey
String firstName;
String lastName;
String zipCode;
String city;
}
Azure Cosmos DB パーティション
- Azure-spring-data-cosmos では、Azure Cosmos DB パーティションがサポートされています。
- ドメイン クラスのフィールドがパーティション キー フィールドになるように指定するには、それに
@PartitionKey
の注釈を付けるだけです。 - CRUD 操作を実行するときに、パーティションの値を指定します。
- パーティション CRUD のその他のサンプルについては、こちらのテストを参照してください。
オプティミスティック ロック
- Azure-spring-data-cosmos では、特定のコンテナーでオプティミスティック ロックがサポートされます。このことは、項目ごとの upsert/削除は、その間に別のプロセスによってその項目が変更されると、例外が発生して失敗することを意味します。
- コンテナーのオプティミスティック ロックを有効にするには、文字列フィールドの
_etag
を作成し、それに@Version
注釈でマークするだけです。 以下を参照してください。
@Container(containerName = "myContainer")
public class MyItem {
String id;
String data;
@Version
String _etag;
}
- オプティミスティック ロックの詳細 については、こちらを参照してください
Spring Data カスタム クエリ、ページング、並べ替え
- Azure-spring-data-cosmos では、Spring Data カスタム クエリがサポートされています。
- たとえば、検索操作 (
findByAFieldAndBField
など) です。 - Spring Data の Pageable、Slice、Sort がサポートされています。
- cosmosDB では、データベース アカウントで使用可能な RU に基づいて、要求されたサイズ以下の項目を返すことができます。
- このように、イテレーションごとに返される項目の数が変わるため、ユーザーは totalPageSize を使用することはできません。代わりに、このようにページングによるイテレーションを行う必要があります。
private List<T> findAllWithPageSize(int pageSize) {
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null);
Page<T> page = repository.findAll(pageRequest);
List<T> pageContent = page.getContent();
while (page.hasNext()) {
Pageable nextPageable = page.nextPageable();
page = repository.findAll(nextPageable);
pageContent = page.getContent();
}
return pageContent;
}
public interface SliceQueriesUserRepository extends CosmosRepository<User, String> {
@Query("select * from c where c.lastName = @lastName")
Slice<User> getUsersByLastName(@Param("lastName") String lastName, Pageable pageable);
}
private List<User> getUsersByLastName(String lastName, int pageSize) {
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null);
Slice<User> slice = repository.getUsersByLastName(lastName, pageRequest);
List<User> content = slice.getContent();
while (slice.hasNext()) {
Pageable nextPageable = slice.nextPageable();
slice = repository.getUsersByLastName(lastName, nextPageable);
content.addAll(slice.getContent());
}
return content;
}
Spring Boot Starter Data Rest
- Azure-spring-data-cosmos では、spring-boot-starter-data-rest がサポートされています。
- ドメイン クラスのリストおよび入れ子にされた型がサポートされています。
- 一意の名前
cosmosObjectMapper
を持つ構成可能な ObjectMapper Bean は、実際に必要な場合にのみカスタマイズされた ObjectMapper を構成します。たとえば、
@Bean(name = "cosmosObjectMapper")
public ObjectMapper objectMapper() {
return new ObjectMapper(); // Do configuration to the ObjectMapper if required
}
監査
- Azure-spring-data-cosmos では、標準の spring-data 注釈を使用して、データベース エンティティ上で監査フィールドがサポートされます。
- この機能を有効にするには、
@EnableCosmosAuditing
注釈をアプリケーション構成に追加します。 - エンティティは、
@CreatedBy
、@CreatedDate
、@LastModifiedBy
、@LastModifiedDate
を使用してフィールドに注釈を付けることができます。 これらのフィールドは自動的に更新されます。
@Container(containerName = "myContainer")
public class AuditableUser {
private String id;
private String firstName;
@CreatedBy
private String createdBy;
@CreatedDate
private OffsetDateTime createdDate;
@LastModifiedBy
private String lastModifiedBy;
@LastModifiedDate
private OffsetDateTime lastModifiedByDate;
}
マルチデータベース構成
- Azure-spring-data-cosmos では、"マルチデータベース アカウント"および "マルチデータベースを使用した単一アカウント" を含む、マルチデータベース構成がサポートされています。
マルチデータベース アカウント
この例では、application.properties
ファイルを使用します。
# primary account cosmos config
azure.cosmos.primary.uri=your-primary-cosmosDb-uri
azure.cosmos.primary.key=your-primary-cosmosDb-key
azure.cosmos.primary.secondaryKey=your-primary-cosmosDb-secondary-key
azure.cosmos.primary.database=your-primary-cosmosDb-dbName
azure.cosmos.primary.populateQueryMetrics=if-populate-query-metrics
# secondary account cosmos config
azure.cosmos.secondary.uri=your-secondary-cosmosDb-uri
azure.cosmos.secondary.key=your-secondary-cosmosDb-key
azure.cosmos.secondary.secondaryKey=your-secondary-cosmosDb-secondary-key
azure.cosmos.secondary.database=your-secondary-cosmosDb-dbName
azure.cosmos.secondary.populateQueryMetrics=if-populate-query-metrics
エンティティとリポジトリの定義は上記と同様です。 異なるデータベース エンティティを別のパッケージに格納することができます。
@EnableReactiveCosmosRepositories
または@EnableCosmosRepositories
では、ユーザー定義の Cosmos テンプレートがサポートされています。reactiveCosmosTemplateRef
またはcosmosTemplateRef
を使用して、検出されたリポジトリで使用するReactiveCosmosTemplate
またはCosmosTemplate
Bean の名前を構成します。複数の Cosmos データベース アカウントがある場合、複数の
CosmosAsyncClient
を定義できます。 単一の Cosmos アカウントに複数のデータベースがある場合は、同じCosmosAsyncClient
を使用して Cosmos テンプレートを初期化できます。
@Configuration
@EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.multiple.account.repository",
reactiveCosmosTemplateRef = "primaryDatabaseTemplate")
public class PrimaryDatasourceConfiguration extends AbstractCosmosConfiguration{
private static final String PRIMARY_DATABASE = "primary_database";
@Bean
@ConfigurationProperties(prefix = "azure.cosmos.primary")
public CosmosProperties primary() {
return new CosmosProperties();
}
@Bean
public CosmosClientBuilder primaryClientBuilder(@Qualifier("primary") CosmosProperties primaryProperties) {
return new CosmosClientBuilder()
.key(primaryProperties.getKey())
.endpoint(primaryProperties.getUri());
}
@Bean
public ReactiveCosmosTemplate primaryDatabaseTemplate(CosmosAsyncClient cosmosAsyncClient,
CosmosConfig cosmosConfig,
MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, PRIMARY_DATABASE, cosmosConfig, mappingCosmosConverter);
}
@Override
protected String getDatabaseName() {
return PRIMARY_DATABASE;
}
}
@Configuration
@EnableCosmosRepositories(cosmosTemplateRef = "secondaryDatabaseTemplate")
public class SecondaryDatasourceConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(SecondaryDatasourceConfiguration.class);
public static final String SECONDARY_DATABASE = "secondary_database";
@Bean
@ConfigurationProperties(prefix = "azure.cosmos.secondary")
public CosmosProperties secondary() {
return new CosmosProperties();
}
@Bean("secondaryCosmosClient")
public CosmosAsyncClient getCosmosAsyncClient(@Qualifier("secondary") CosmosProperties secondaryProperties) {
return CosmosFactory.createCosmosAsyncClient(new CosmosClientBuilder()
.key(secondaryProperties.getKey())
.endpoint(secondaryProperties.getUri()));
}
@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(true)
.maxDegreeOfParallelism(0)
.maxBufferedItemCount(0)
.responseContinuationTokenLimitInKb(0)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
@Bean
public CosmosTemplate secondaryDatabaseTemplate(@Qualifier("secondaryCosmosClient") CosmosAsyncClient client,
@Qualifier("secondaryCosmosConfig") CosmosConfig cosmosConfig,
MappingCosmosConverter mappingCosmosConverter) {
return new CosmosTemplate(client, SECONDARY_DATABASE, cosmosConfig, mappingCosmosConverter);
}
private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {
@Override
public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
LOGGER.info("Response Diagnostics {}", responseDiagnostics);
}
}
}
- 上記の例では、Cosmos アカウントは2 つあります。
CosmosAsyncClient
を次のように作成できます。
@Bean("secondaryCosmosClient")
public CosmosAsyncClient getCosmosAsyncClient(@Qualifier("secondary") CosmosProperties secondaryProperties) {
return CosmosFactory.createCosmosAsyncClient(new CosmosClientBuilder()
.key(secondaryProperties.getKey())
.endpoint(secondaryProperties.getUri()));
}
@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(true)
.maxDegreeOfParallelism(0)
.maxBufferedItemCount(0)
.responseContinuationTokenLimitInKb(0)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
- また、、
maxBufferedItemCount
maxDegreeOfParallelism
またはresponseContinuationTokenLimitInKb
を定義queryMetricsEnabled
ResponseDiagnosticsProcessor
する場合は、Cosmos テンプレートの をCosmosConfig
作成できます。
@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(true)
.maxDegreeOfParallelism(0)
.maxBufferedItemCount(0)
.responseContinuationTokenLimitInKb(0)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
- アプリケーション クラスを作成する
@SpringBootApplication
public class MultiDatabaseApplication implements CommandLineRunner {
@Autowired
private CosmosUserRepository cosmosUserRepository;
@Autowired
private MysqlUserRepository mysqlUserRepository;
@Autowired
@Qualifier("secondaryDatabaseTemplate")
private CosmosTemplate secondaryDatabaseTemplate;
@Autowired
@Qualifier("primaryDatabaseTemplate")
private ReactiveCosmosTemplate primaryDatabaseTemplate;
private final CosmosUser cosmosUser = new CosmosUser("1024", "1024@geek.com", "1k", "Mars");
private static CosmosEntityInformation<CosmosUser, String> userInfo = new CosmosEntityInformation<>(CosmosUser.class);
public static void main(String[] args) {
SpringApplication.run(MultiDatabaseApplication.class, args);
}
public void run(String... var1) throws Exception {
CosmosUser cosmosUserGet = primaryDatabaseTemplate.findById(cosmosUser.getId(), cosmosUser.getClass()).block();
// Same to this.cosmosUserRepository.findById(cosmosUser.getId()).block();
MysqlUser mysqlUser = new MysqlUser(cosmosUserGet.getId(), cosmosUserGet.getEmail(), cosmosUserGet.getName(), cosmosUserGet.getAddress());
mysqlUserRepository.save(mysqlUser);
mysqlUserRepository.findAll().forEach(System.out::println);
CosmosUser secondaryCosmosUserGet = secondaryDatabaseTemplate.findById(CosmosUser.class.getSimpleName(), cosmosUser.getId(), CosmosUser.class);
System.out.println(secondaryCosmosUserGet);
}
@PostConstruct
public void setup() {
primaryDatabaseTemplate.createContainerIfNotExists(userInfo).block();
primaryDatabaseTemplate.insert(CosmosUser.class.getSimpleName(), cosmosUser, new PartitionKey(cosmosUser.getName())).block();
// Same to this.cosmosUserRepository.save(user).block();
secondaryDatabaseTemplate.createContainerIfNotExists(userInfo);
secondaryDatabaseTemplate.insert(CosmosUser.class.getSimpleName(), cosmosUser, new PartitionKey(cosmosUser.getName()));
}
@PreDestroy
public void cleanup() {
primaryDatabaseTemplate.deleteAll(CosmosUser.class.getSimpleName(), CosmosUser.class).block();
// Same to this.cosmosUserRepository.deleteAll().block();
secondaryDatabaseTemplate.deleteAll(CosmosUser.class.getSimpleName() , CosmosUser.class);
mysqlUserRepository.deleteAll();
}
}
マルチデータベースを使用した単一アカウント
この例では、application.properties
ファイルを使用します。
azure.cosmos.uri=your-cosmosDb-uri
azure.cosmos.key=your-cosmosDb-key
azure.cosmos.secondary-key=your-cosmosDb-secondary-key
azure.cosmos.database=your-cosmosDb-dbName
azure.cosmos.populate-query-metrics=if-populate-query-metrics
- エンティティとリポジトリの定義は上記と同様です。 異なるデータベース エンティティを別のパッケージに格納することができます。
EnableReactiveCosmosRepositories
を別のreactiveCosmosTemplateRef
とともに使用して、単一の Cosmos アカウントに複数のデータベースを定義できます。
@Configuration
public class DatasourceConfiguration {
private static final String DATABASE1 = "database1";
private static final String DATABASE2 = "database2";
@Bean
public CosmosProperties cosmosProperties() {
return new CosmosProperties();
}
@Bean
public CosmosClientBuilder primaryClientBuilder(CosmosProperties cosmosProperties) {
return new CosmosClientBuilder()
.key(cosmosProperties.getKey())
.endpoint(cosmosProperties.getUri());
}
@EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.repository1",
reactiveCosmosTemplateRef = "database1Template")
public class Database1Configuration extends AbstractCosmosConfiguration {
@Bean
public ReactiveCosmosTemplate database1Template(CosmosAsyncClient cosmosAsyncClient,
CosmosConfig cosmosConfig,
MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, DATABASE1, cosmosConfig, mappingCosmosConverter);
}
@Override
protected String getDatabaseName() {
return DATABASE1;
}
}
@EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.repository2",
reactiveCosmosTemplateRef = "database2Template")
public class Database2Configuration {
@Bean
public ReactiveCosmosTemplate database2Template(CosmosAsyncClient cosmosAsyncClient,
CosmosConfig cosmosConfig,
MappingCosmosConverter mappingCosmosConverter) {
return new ReactiveCosmosTemplate(cosmosAsyncClient, DATABASE2, cosmosConfig, mappingCosmosConverter);
}
}
}
- アプリケーション クラスを作成する
@SpringBootApplication
public class MultiDatabaseApplication implements CommandLineRunner {
@Autowired
private User1Repository user1Repository;
@Autowired
@Qualifier("database1Template")
private ReactiveCosmosTemplate database1Template;
@Autowired
@Qualifier("database2Template")
private ReactiveCosmosTemplate database2Template;
private final User1 user1 = new User1("1024", "1024@geek.com", "1k", "Mars");
private static CosmosEntityInformation<User1, String> user1Info = new CosmosEntityInformation<>(User1.class);
private final User2 user2 = new User2("2048", "2048@geek.com", "2k", "Mars");
private static CosmosEntityInformation<User2, String> user2Info = new CosmosEntityInformation<>(User2.class);
public static void main(String[] args) {
SpringApplication.run(MultiDatabaseApplication.class, args);
}
public void run(String... var1) throws Exception {
User1 database1UserGet = database1Template.findById(User1.class.getSimpleName(), user1.getId(), User1.class).block();
// Same to userRepository1.findById(user.getId()).block()
System.out.println(database1UserGet);
User2 database2UserGet = database2Template.findById(User2.class.getSimpleName(), user2.getId(), User2.class).block();
System.out.println(database2UserGet);
}
@PostConstruct
public void setup() {
database1Template.createContainerIfNotExists(user1Info).block();
database1Template.insert(User1.class.getSimpleName(), user1, new PartitionKey(user1.getName())).block();
// Same to this.userRepository1.save(user).block();
database2Template.createContainerIfNotExists(user2Info).block();
database2Template.insert(User2.class.getSimpleName(), user2, new PartitionKey(user2.getName())).block();
}
@PreDestroy
public void cleanup() {
database1Template.deleteAll(User1.class.getSimpleName(), User1.class).block();
// Same to this.userRepository1.deleteAll().block();
database2Template.deleteAll(User2.class.getSimpleName(), User2.class).block();
}
}
データベース レベルでのマルチテナント
- Azure-spring-data-cosmos では、getDatabaseName() 関数を
CosmosFactory
拡張してオーバーライドすることで、データベース レベルの構成でマルチテナントをサポートしています。
public class MultiTenantDBCosmosFactory extends CosmosFactory {
private String tenantId;
/**
* Validate config and initialization
*
* @param cosmosAsyncClient cosmosAsyncClient
* @param databaseName databaseName
*/
public MultiTenantDBCosmosFactory(CosmosAsyncClient cosmosAsyncClient, String databaseName) {
super(cosmosAsyncClient, databaseName);
this.tenantId = databaseName;
}
@Override
public String getDatabaseName() {
return this.getCosmosAsyncClient().getDatabase(this.tenantId).toString();
}
}
ベータ版パッケージ
main
ブランチから構築されたベータ版を利用できます。ベータ版のパッケージを使用するための説明を参照してください。
トラブルシューティング
全般
バグが発生した場合は、 ここで問題を報告してください。
新しい機能または変更された可能性のある変更を提案するには、バグの場合と同じ方法で問題を報告します。
クライアントのログ記録を有効にする
- Azure-spring-data-cosmos では、log4j や logback などの一般的なログ記録フレームワークへのログ記録をサポートするロギング ファサードとして SLF4j が使用されます。 たとえば、ログ記録フレームワークとして Spring Logback を使用する場合、次の xml をリソース フォルダーに追加します。
<configuration>
<include resource="/org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<logger name="com.azure.cosmos" level="error"/>
<logger name="org.springframework" level="error"/>
<logger name="io.netty" level="error"/>
<!-- This will enable query logging, to include query parameter logging, set this logger to TRACE -->
<logger name="com.azure.cosmos.implementation.SqlQuerySpecLogger" level="DEBUG"/>
</configuration>
例
- このサンプル プロジェクトを参照してください。
マルチデータベース アカウント
- マルチデータベースのサンプル プロジェクトを参照してください。
マルチデータベースを使用した単一アカウント
- マルチデータベースを使用した単一アカウントのサンプル プロジェクトを参照してください。
次のステップ
- Azure Spring Data Cosmos の詳細 については、こちらを参照してください。
- Azure CosmosDB Service の詳細を確認してください。
共同作成
このプロジェクトでは、共同作成と提案を歓迎しています。 ほとんどの共同作成では、共同作成者使用許諾契約書 (CLA) にご同意いただき、ご自身の共同作成内容を使用する権利を Microsoft に供与する権利をお持ちであり、かつ実際に供与することを宣言していただく必要があります。
pull request を送信すると、CLA を提供して PR (ラベル、コメントなど) を適宜装飾する必要があるかどうかを CLA ボットが自動的に決定します。 ボットによって提供される手順にそのまま従ってください。 この操作は、Microsoft の CLA を使用するすべてのリポジトリについて、1 回だけ行う必要があります。
このプロジェクトでは、Microsoft オープン ソースの倫理規定を採用しています。 詳しくは、「Code of Conduct FAQ (倫理規定についてよくある質問)」を参照するか、opencode@microsoft.com 宛てに質問またはコメントをお送りください。