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 StringQuery 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提供してカスタマイズできます。、、 をカスタマイズ nonPointOperationLatencyThresholdInMSCosmosAsyncClientpointOperationLatencyThresholdInMSrequestChargeThresholdInRUして、 と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 として使用されます。 item idなどの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 クエリの詳細については、次の記事を参照してください。

アプリケーション クラスを作成する

ここでは、すべてのコンポーネントを含むアプリケーション クラスを作成します。

@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();
}
  • また、、 maxBufferedItemCountmaxDegreeOfParallelismまたは responseContinuationTokenLimitInKb を定義queryMetricsEnabledResponseDiagnosticsProcessorする場合は、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>

マルチデータベース アカウント

マルチデータベースを使用した単一アカウント

次のステップ

共同作成

このプロジェクトでは、共同作成と提案を歓迎しています。 ほとんどの共同作成では、共同作成者使用許諾契約書 (CLA) にご同意いただき、ご自身の共同作成内容を使用する権利を Microsoft に供与する権利をお持ちであり、かつ実際に供与することを宣言していただく必要があります。

pull request を送信すると、CLA を提供して PR (ラベル、コメントなど) を適宜装飾する必要があるかどうかを CLA ボットが自動的に決定します。 ボットによって提供される手順にそのまま従ってください。 この操作は、Microsoft の CLA を使用するすべてのリポジトリについて、1 回だけ行う必要があります。

このプロジェクトでは、Microsoft オープン ソースの倫理規定を採用しています。 詳しくは、「Code of Conduct FAQ (倫理規定についてよくある質問)」を参照するか、opencode@microsoft.com 宛てに質問またはコメントをお送りください。

インプレッション数