Bibliothèque de client Azure Spring Data Cosmos pour Java - version 5.6.0
Azure Spring Data Cosmos assure la prise en charge de Spring Data pour Azure Cosmos DB à l’aide de l’API SQL, basée sur le framework Spring Data. Azure Cosmos DB est un service de base de données distribué à l’échelle mondiale qui permet aux développeurs de travailler sur des données à l’aide de diverses API standard, telles que SQL, MongoDB, Cassandra, Graph et Table.
Stratégie de support Spring Boot
Ce projet prend en charge plusieurs versions de Spring Boot. Pour obtenir la liste complète des versions actuellement prises en charge, consultez notre mappage de versions Spring.
Les versions Spring Boot sont marquées « Fin de vie » lorsqu’elles ne sont plus prises en charge ou publiées sous une quelconque forme. Si vous exécutez une version EOL, vous devez effectuer une mise à niveau dès que possible.
Notez qu’une version peut ne pas être prise en charge avant d’être marquée comme « Fin de vie ». Pendant ce temps, vous ne devez attendre que des mises en production pour des bogues critiques ou des problèmes de sécurité.
Pour plus d’informations sur les versions prises en charge de Spring Boot, consultez Versions prises en charge de Spring Boot.
Prise en charge des versions de Spring Boot
Les utilisateurs de Maven peuvent hériter du projet spring-boot-starter-parent
pour obtenir une section de gestion des dépendances afin de permettre à Spring de gérer les versions des dépendances.
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
</parent>
Avec cette configuration, vous pouvez également substituer des dépendances individuelles en substituant une propriété dans votre propre projet. Par exemple, pour passer à un autre train de livraison (release train) Spring Data, vous devez ajouter ce qui suit à votre fichier pom.xml.
<properties>
<spring-data-releasetrain.version>${spring.data.version}</spring-data-releasetrain.version>
</properties>
Si vous ne souhaitez pas utiliser spring-boot-starter-parent
, vous pouvez tout de même conserver l’avantage de la gestion des dépendances en utilisant une dépendance 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>
Quelle version d’Azure Spring Data Cosmos dois-je utiliser ?
Mappage de la version Spring Boot / Spring Cloud aux versions d’Azure Spring Data Cosmos
Version de Spring Boot | Version de Spring Cloud | Versions d’Azure Spring Data Cosmos |
---|---|---|
3.0.x | 2022.0.x | 5.3.0 et versions ultérieures |
2.7.x | 2021.0.x | 3.23.0 et versions ultérieures |
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 |
J’utilise Spring Boot version X
Si vous utilisez Spring Boot dans votre projet, vous trouverez les versions d’Azure Spring Data Cosmos associées dans le tableau ci-dessus. Par exemple : si vous utilisez Spring Boot 3.0.x, vous devez utiliser Azure Spring Data Cosmos versions 5.3.0 et ultérieures.
J’utilise Spring Cloud Version Y
Si vous utilisez Spring Cloud dans votre projet, vous pouvez également trouver les versions Azure Spring Data Cosmos associées dans le tableau ci-dessus. Par exemple, si vous utilisez Spring Cloud 2022.0.x, vous devez utiliser Azure Spring Data Cosmos versions 5.3.0 et ultérieures.
Prise en charge des versions de Spring Data
Ce projet prend en charge les spring-data-commons 3.0.x
versions.
La configuration ci-dessus ne vous permet pas de remplacer des dépendances individuelles à l’aide d’une propriété, comme expliqué ci-dessus. Pour obtenir le même résultat, vous devez ajouter une entrée dans la partie dependencyManagement de votre projet avant l’entrée spring-boot-dependencies
. Par exemple, pour passer à un autre train de livraison (release train) Spring Data, vous devez ajouter ce qui suit à votre fichier 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>
Remarque : Remplacez ${spring.boot.version} et ${spring.data.version} par les versions de Spring Boot et de Spring Data que vous souhaitez utiliser dans votre projet.
Prise en main
Inclure le package
Si vous utilisez Maven, ajoutez la dépendance suivante.
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-spring-data-cosmos</artifactId>
<version>5.6.0</version>
</dependency>
Prérequis
- Kit de développement Java (JDK), version 8 ou ultérieure.
- Un compte Azure actif. Si vous n’en avez pas, vous pouvez vous inscrire pour bénéficier d’un compte gratuit. Vous pouvez également utiliser l’émulateur Azure Cosmos DB à des fins de développement et de test. Comme le certificat https de l’émulateur est auto-signé, vous devez importer son certificat dans le magasin de certificats approuvé Java, expliqué ici
- (Facultatif) SLF4J est une façade de journalisation.
- (Facultatif) La liaison SLF4J est utilisée pour associer un framework de journalisation spécifique à SLF4J.
- (Facultatif) Maven
SLF4J n’est nécessaire que si vous envisagez d’utiliser la journalisation. Téléchargez également une liaison SLF4J qui lie l’API SLF4J à l’implémentation de journalisation de votre choix. Pour plus d’informations, consultez le manuel de l’utilisateur SLF4J.
Installer la classe de configuration
Pour installer la classe de configuration, vous devez étendre
AbstractCosmosConfiguration
.Azure-spring-data-cosmos prend également en charge
Response Diagnostics String
,Query Metrics
etMax Degree of Parallelism
. Définissez l’indicateurqueryMetricsEnabled
avec la valeur true dans application.properties pour activer les métriques de requête. En plus de définir l’indicateur, implémentezResponseDiagnosticsProcessor
pour journaliser les informations de diagnostic. Définissez l’indicateur sur un entier dans application.properties pour autoriser le traitement parallèle ; si vous définissezmaxDegreeOfParallelism
la valeur sur -1, le SDK décide de la valeur optimale. DéfinissezmaxBufferedItemCount
l’indicateur sur un entier dans application.properties pour permettre à l’utilisateur de définir le nombre maximal d’éléments pouvant être mis en mémoire tampon pendant l’exécution d’une requête parallèle ; si la valeur est inférieure à 0, le système décide automatiquement du nombre d’éléments à mettre en mémoire tampon. REMARQUE : La définition d’une valeur très élevée peut entraîner une consommation élevée de mémoire. DéfinissezresponseContinuationTokenLimitInKb
l’indicateur sur un entier dans application.properties pour permettre à l’utilisateur de limiter la longueur du jeton de continuation dans la réponse à la requête. Le jeton de continuation contient à la fois les champs obligatoires et facultatifs. Les champs obligatoires sont nécessaires pour reprendre l’exécution à partir de l’endroit où elle a été arrêtée. Les champs facultatifs peuvent contenir un travail de recherche d’index sérialisé qui a été effectué mais qui n’a pas encore été utilisé. Cela évite de refaire le travail dans les continuations suivantes et, par conséquent, améliore les performances des requêtes. Si vous définissez la taille de continuation maximale sur 1 Ko, le service Azure Cosmos DB sérialise uniquement les champs obligatoires. À partir de 2 Ko, le service Azure Cosmos DB sérialise autant qu’il peut le faire jusqu’à ce qu’il atteigne la taille maximale spécifiée. DéfinissezpointOperationLatencyThresholdInMS
,nonPointOperationLatencyThresholdInMS
etpayloadSizeThresholdInBytes
requestChargeThresholdInRU
pour activer diagnostics au niveau du client lorsque ces seuils sont dépassés.
@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);
}
}
}
Personnalisation de la configuration
Vous pouvez personnaliser DirectConnectionConfig
ou ou GatewayConnectionConfig
les deux et leur fournir le CosmosClientBuilder
bean pour personnaliserCosmosAsyncClient
. Vous pouvez personnaliser pointOperationLatencyThresholdInMS
, requestChargeThresholdInRU
nonPointOperationLatencyThresholdInMS
et payloadSizeThresholdInBytes
pour personnaliser les seuils de journalisation des diagnostics lorsqu’ils sont combinés avec CosmosDiagnosticsHandler
ce qui active la journalisation des diagnostics avec les seuils par défaut lors de l’ajout à .CosmosClientBuilder
@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();
}
Par défaut, @EnableCosmosRepositories
analyse le package actuel à la recherche d’interfaces qui étendent l’une des interfaces de référentiel de Spring Data.
Utilisez-le pour annoter votre classe Configuration afin d’analyser un autre package racine avec @EnableCosmosRepositories(basePackageClass=UserRepository.class)
si la disposition de votre projet compte plusieurs projets.
Activation de la journalisation diagnostics dans Azure Application Insights avec JavaAgent
Les diagnostics peuvent être activés en passant le JavaAgent avec votre application, comme ci-dessous. Cette opération active la journalisation avec les seuils par défaut. Le « -javaagent » doit être passé avant « -jar ».
java -javaagent:"<path-to-applicationinsights-agent-jar>" -jar <myapp.jar>
Utilisation du débit approvisionné de base de données
Cosmos prend en charge le débit provisionné pour les conteneurs et les bases de données . Par défaut, spring-data-cosmos provisionne le débit pour chaque conteneur créé. Si vous préférez partager le débit entre les conteneurs, vous pouvez activer le débit approvisionné par la base de données via CosmosConfig.
@Override
public CosmosConfig cosmosConfig() {
int autoscale = false;
int initialRequestUnits = 400;
return CosmosConfig.builder()
.enableDatabaseThroughput(autoscale, initialRequestUnits)
.build();
}
Définir une entité
Définissez une entité simple en tant qu’élément dans Azure Cosmos DB.
Vous pouvez définir des entités en ajoutant l’annotation
@Container
et en spécifiant des propriétés associées au conteneur, notamment le nom du conteneur, les unités de requête (RU), la durée de vie et la création automatique du conteneur.Sauf si vous spécifiez le contraire, les conteneurs sont créés automatiquement. Définissez
autoCreateContainer
avec la valeur false dans l’annotation@Container
pour désactiver la création automatique des conteneurs.Remarque : Par défaut, 400 unités de requête sont affectées aux conteneurs nouvellement créés. Spécifiez une valeur ru différente afin de personnaliser les unités de requête pour le conteneur créé par le SDK (la valeur RU minimale est 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
le champ sera utilisé comme ID d’élément dans Azure Cosmos DB. Si vous souhaitez utiliser un autre champ commefirstName
élémentid
, il vous suffit d’annoter ce champ avec@Id
une annotation.L’annotation
@Container(containerName="myContainer")
spécifie le nom du conteneur dans Azure Cosmos DB.L’annotation
@PartitionKey
du champlastName
spécifie ce champ en tant que clé de partition dans Azure Cosmos DB.
Création de conteneurs avec débit de mise à l’échelle automatique
- S’il est défini avec la valeur true, le champ d’annotation
autoScale
spécifie que le conteneur doit être créé avec un débit de mise à l’échelle automatique. La valeur par défaut est false, ce qui signifie que les conteneurs sont créés avec un débit manuel. - Pour plus d’informations sur le débit de mise à l’échelle automatique, cliquez ici.
@Container(containerName = "myContainer", autoScale = true, ru = "4000")
public class UserSample {
@Id
private String emailAddress;
}
Prise en charge des clés de partition imbriquées
- Azure Spring Data Cosmos prend en charge la clé de partition imbriquée. Pour ajouter une clé de partition imbriquée, utilisez le champ
partitionKeyPath
dans l’annotation@Container
. - Utilisez uniquement
partitionKeyPath
pour prendre en charge le chemin à la clé de partition imbriquée. Pour la prise en charge générale des clés de partition, utilisez l’annotation@PartitionKey
. - L’annotation
@PartitionKey
est prioritaire par défaut, sauf si elle n’est pas spécifiée. - L’exemple ci-dessous montre comment utiliser correctement la fonctionnalité de clé de partition imbriquée.
@Container(containerName = "nested-partition-key", partitionKeyPath = "/nestedEntitySample/nestedPartitionKey")
public class NestedPartitionKeyEntitySample {
private NestedEntitySample nestedEntitySample;
}
public class NestedEntitySample {
private String nestedPartitionKey;
}
Créer des référentiels
Étend l’interface CosmosRepository, qui prend en charge les référentiels Spring Data.
@Repository
public interface UserRepository extends CosmosRepository<User, String> {
Iterable<User> findByFirstName(String firstName);
long countByFirstName(String firstName);
User findOne(String id, String lastName);
}
- La méthode
findByFirstName
est une méthode de requête personnalisée qui trouve des éléments par prénom (firstName).
Mise en cache d’un plan de requête
Les API de requête spring repository telles que findByFirstName(String firstName)
l’emplacement de firstName
la partition ou les requêtes annotées contenant la clé de partition réduisent le temps d’exécution des requêtes en raison de la mise en cache du plan de requête. Actuellement, la mise en cache du plan de requête n’est prise en charge que pour les méthodes de requête ciblant une seule partition.
QueryAnnotation : utilisation de requêtes annotées dans les référentiels
Azure Spring Data Cosmos prend en charge la spécification de requêtes annotées dans les référentiels avec @Query
.
- Exemples de requêtes annotées dans CosmosRepository synchrone :
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);
}
- Exemples de requêtes annotées dans 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);
}
Les requêtes spécifiées dans l’annotation sont identiques aux requêtes Cosmos. Pour plus d’informations sur les requêtes SQL dans Cosmos, consultez les articles suivants.
- [Sql API Query Prise en main] sql_queries_getting_started
- [Didacticiel sur les requêtes d’API Sql] sql_queries_in_cosmos
Créer une classe Application
Voici comment créer une classe Application avec tous les composants :
@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);
}
}
- Câblez automatiquement l’interface UserRepository pour effectuer des opérations telles que l’enregistrement, la suppression, la recherche, etc.
- Spring Data Azure Cosmos DB utilise
CosmosTemplate
etReactiveCosmosTemplate
pour exécuter les requêtes derrière les méthodes find et save. Vous pouvez utiliser le modèle vous-même pour des requêtes plus complexes.
Concepts clés
CrudRepository et ReactiveCrudRepository
- Azure Spring Data Cosmos prend en charge ReactiveCrudRepository et CrudRepository, qui fournissent des fonctionnalités CRUD de base.
- Enregistrer
- findAll
- findOne by ID
- deleteAll
- supprimer par ID
- delete entity
Annotations Spring Data
Annotation spring Data @Id
Il existe deux façons de mapper un champ d’une classe de domaine au champ id
d’un élément Azure Cosmos DB.
- Annoter un champ dans une classe de domaine avec
@Id
, ce champ étant mappé à l’id
d’élément dans Cosmos DB. - Définir le nom de ce champ sur
id
, ce champ étant mappé à l’id
d’élément dans Cosmos DB.
Génération automatique d’ID
- Prend en charge la génération automatique d’UUID de type chaîne avec l’annotation @GeneratedValue. Le champ id d’une entité avec un ID de type chaîne peut être annoté avec
@GeneratedValue
pour générer automatiquement un UUID aléatoire avant l’insertion.
public class GeneratedIdEntity {
@Id
@GeneratedValue
private String id;
}
Expression SpEL et nom de conteneur personnalisé.
- Par défaut, le nom du conteneur est le nom de la classe du domaine de l’utilisateur. Pour le personnaliser, ajoutez l’annotation
@Container(containerName="myCustomContainerName")
à la classe de domaine. Le champ conteneur prend également en charge les expressions SpEL (par exemplecontainer = "${dynamic.container.name}"
, oucontainer = "#{@someBean.getContainerName()}"
) afin de fournir des noms de conteneur par programmation/via des propriétés de configuration. - Pour que les expressions SpEL fonctionnent correctement, vous devez ajouter
@DependsOn("expressionResolver")
au-dessus de la classe Spring Application.
@SpringBootApplication
@DependsOn("expressionResolver")
public class SampleApplication {
}
Stratégie d’indexation
- Par défaut, IndexingPolicy est défini par le service portail Azure. Pour le personnaliser, ajoutez l’annotation
@CosmosIndexingPolicy
à la classe de domaine. Cette annotation a 5 attributs à personnaliser, consultez les rubriques suivantes :
// 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 {};
Stratégie de clé unique
- Azure Spring Data Cosmos prend en charge la définition
UniqueKeyPolicy
sur le conteneur en ajoutant l’annotation@CosmosUniqueKeyPolicy
à la classe de domaine. Cette annotation a les attributs suivants :
@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;
}
Partition Azure Cosmos DB
- Azure-spring-data-cosmos prend en charge les partitions Azure Cosmos DB.
- Pour spécifier un champ d’une classe de domaine comme champ de clé de partition, annotez-le simplement avec
@PartitionKey
. - Quand vous effectuez une opération CRUD, spécifiez la valeur de votre partition.
- Pour plus d’exemples sur les opérations CRUD sur les partitions, consultez le test ici.
Verrouillage optimiste
- Azure-spring-data-cosmos prend en charge le verrouillage optimiste pour des conteneurs spécifiques, ce qui signifie que les upserts/suppressions par élément échouent avec une exception quand l’élément est modifié par un autre processus entre-temps.
- Pour activer le verrouillage optimiste pour un conteneur, créez simplement un champ
_etag
de type chaîne et marquez-le avec l’annotation@Version
. Consultez les rubriques suivantes :
@Container(containerName = "myContainer")
public class MyItem {
String id;
String data;
@Version
String _etag;
}
- En savoir plus sur Verrouillage optimiste ici
Requête personnalisée Spring Data, pagination et tri
- Azure-spring-data-cosmos prend en charge les requêtes personnalisées Spring Data.
- Exemple d’opération de recherche :
findByAFieldAndBField
. - Prend en charge les types Spring Data Pageable, Slice et Sort.
- En fonction des unités de requête disponibles sur le compte de base de données, Cosmos DB peut retourner des éléments inférieurs ou égaux à la taille demandée.
- En raison du nombre variable d’éléments retournés dans chaque itération, l’utilisateur ne doit pas se fier à totalPageSize. Au lieu de cela, effectuez l’itération sur Pageable de cette façon.
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 prend en charge spring-boot-starter-data-rest.
- Prend en charge les listes et le type imbriqué dans la classe de domaine.
- Haricot ObjectMapper configurable avec un nom
cosmosObjectMapper
unique , configurez uniquement objectMapper personnalisé si vous en avez vraiment besoin. par exemple,
@Bean(name = "cosmosObjectMapper")
public ObjectMapper objectMapper() {
return new ObjectMapper(); // Do configuration to the ObjectMapper if required
}
Audit
- Azure-spring-data-cosmos prend en charge l’audit des champs sur des entités de base de données à l’aide d’annotations Spring Data standard.
- Cette fonctionnalité peut être activée en ajoutant une annotation
@EnableCosmosAuditing
à la configuration de votre application. - Les entités peuvent annoter des champs avec
@CreatedBy
,@CreatedDate
,@LastModifiedBy
et@LastModifiedDate
. Ces champs seront mis à jour automatiquement.
@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;
}
Configuration de plusieurs bases de données
- Azure-spring-data-cosmos prend en charge la configuration de plusieurs bases de données, notamment « plusieurs comptes de base de données » et « un seul compte, plusieurs bases de données ».
Plusieurs comptes de base de données
L’exemple utilise le fichier 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
La définition d’Entity et de Repository est semblable à celle ci-dessus. Vous pouvez placer différentes entités de base de données dans différents packages.
@EnableReactiveCosmosRepositories
et@EnableCosmosRepositories
prennent en charge les modèles Cosmos définis par l’utilisateur. UtilisezreactiveCosmosTemplateRef
oucosmosTemplateRef
pour configurer le nom du beanReactiveCosmosTemplate
ouCosmosTemplate
à utiliser avec les référentiels détectés.Si vous avez plusieurs comptes de base de données Cosmos, vous pouvez définir plusieurs
CosmosAsyncClient
. Si un seul compte Cosmos comprend plusieurs bases de données, vous pouvez utiliser le mêmeCosmosAsyncClient
pour initialiser le modèle 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);
}
}
}
- Dans l’exemple ci-dessus, nous avons deux comptes Cosmos. Vous pouvez créer
CosmosAsyncClient
comme ceci :
@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();
}
- En outre, si vous souhaitez définir
queryMetricsEnabled
,ResponseDiagnosticsProcessor
,maxDegreeOfParallelism
maxBufferedItemCount
ouresponseContinuationTokenLimitInKb
, vous pouvez créer leCosmosConfig
pour votre modèle cosmos.
@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(true)
.maxDegreeOfParallelism(0)
.maxBufferedItemCount(0)
.responseContinuationTokenLimitInKb(0)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
- Créer une classe Application
@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();
}
}
Compte unique avec plusieurs bases de données
L’exemple utilise le fichier 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
- La définition d’Entity et de Repository est semblable à celle ci-dessus. Vous pouvez placer différentes entités de base de données dans différents packages.
- Vous pouvez utiliser
EnableReactiveCosmosRepositories
avec unreactiveCosmosTemplateRef
différent pour définir plusieurs bases de données dans un seul compte 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);
}
}
}
- Créer une classe Application
@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();
}
}
Multi-location au niveau de la base de données
- Azure-spring-data-cosmos prend en charge l’architecture mutualisée au niveau de la base de données en étendant
CosmosFactory
et en remplaçant la fonction getDatabaseName().
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();
}
}
Package de la version bêta
La version bêta générée à partir de la branche main
est disponible. Vous pouvez consulter les instructions pour utiliser des packages en version bêta.
Dépannage
Général
Si vous rencontrez des bogues, signalez un problème ici.
Pour suggérer une nouvelle fonctionnalité ou des modifications, signalez un problème comme vous le feriez pour un bogue.
Activer la journalisation du client
- Azure-spring-data-cosmos utilise log4j comme façade de journalisation prenant en charge la journalisation dans les frameworks de journalisation connus tels que log4j et logback. Par exemple, si vous souhaitez utiliser spring logback comme framework de journalisation, ajoutez le code XML suivant au dossier resources.
<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>
Exemples
- Consultez l’exemple de projet ici.
Plusieurs comptes de base de données
- Consultez l’exemple de projet avec plusieurs bases de données.
Compte unique avec plusieurs bases de données
Étapes suivantes
- Pour en savoir plus sur Azure Spring Data Cosmos , cliquez ici.
- En savoir plus sur le service Azure CosmosDB
Contribution
Ce projet accepte les contributions et les suggestions. La plupart des contributions vous demandent d’accepter un contrat de licence de contribution (CLA) spécifiant que vous avez le droit de nous accorder les droits d’utiliser votre contribution, et que vous nous les accordez.
Quand vous envoyez une demande de tirage (pull request), un bot CLA détermine automatiquement si vous devez fournir un contrat CLA et agrémenter la demande de tirage de façon appropriée (par exemple, avec une étiquette ou un commentaire). Suivez simplement les instructions fournies par le bot. Vous ne devez effectuer cette opération qu’une seule fois sur tous les dépôts utilisant notre contrat CLA.
Ce projet a adopté le Code de conduite Open Source de Microsoft. Pour plus d’informations, consultez les Questions fréquentes (FAQ) sur le code de conduite ou envoyez vos questions ou vos commentaires à opencode@microsoft.com.