Biblioteca de clientes do Azure Spring Data Cosmos para Java – versão 5.6.0
O Azure Spring Data Cosmos dá suporte ao Spring Data para o Azure Cosmos DB usando a API SQL, com base na estrutura do Spring Data. O Azure Cosmos DB é um serviço de banco de dados distribuído globalmente que permite aos desenvolvedores trabalhar com os dados usando várias APIs padrão, como SQL, MongoDB, Cassandra, Graph e de Tabela.
Política de suporte do Spring Boot
Este projeto dá suporte a várias versões do Spring Boot. Para obter uma lista completa das versões suportadas no momento, visite nosso Mapeamento de versão do Spring.
As versões do Spring Boot estão marcadas como "Fim da Vida" quando não têm mais suporte ou são lançadas de forma alguma. Se você estiver executando uma versão do EOL, deverá atualizar o mais rápido possível.
Observe que uma versão pode ficar sem suporte antes de ser marcada como "Fim da Vida Útil". Durante esse tempo, você deve esperar apenas versões para bugs críticos ou problemas de segurança.
Para obter mais informações sobre as versões com suporte do Spring Boot, visite versões com suporte do Spring Boot.
Suporte à versão do Spring Boot
Os usuários do Maven podem herdar do projeto spring-boot-starter-parent
para obter uma seção de gerenciamento de dependência para permitir que o Spring gerencie as versões para as dependências.
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
</parent>
Com essa configuração, você também pode substituir dependências individuais substituindo uma propriedade no seu próprio projeto. Por exemplo, para atualizar para outro treinamento de versão do Spring Data, adicione o item a seguir ao seu pom.xml.
<properties>
<spring-data-releasetrain.version>${spring.data.version}</spring-data-releasetrain.version>
</properties>
Se você não quiser usar o spring-boot-starter-parent
, ainda poderá manter o benefício do gerenciamento de dependência usando uma dependência 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>
Qual versão do Azure Spring Data Cosmos devo usar
Mapeamento da versão do SpringCloud do Spring Boot / para as versões do Azure Spring Data Cosmos
Versão do Spring Boot | Versão do Spring Cloud | Versões do Azure Spring Data Cosmos |
---|---|---|
3.0.x | 2022.0.x | 5.3.0 e superior |
2.7.x | 2021.0.x | 3.23.0 e superior |
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 |
Estou usando a versão X do Spring Boot
Se você estiver usando o Spring Boot em seu projeto, poderá encontrar versões relacionadas do Azure Spring Data Cosmos da tabela acima. Por exemplo: se você estiver usando o Spring Boot 3.0.x, deverá usar o Azure Spring Data Cosmos versões 5.3.0 e superiores.
Estou usando a versão Y do Spring Cloud
Se você estiver usando o Spring Cloud em seu projeto, também poderá encontrar versões relacionadas do Azure Spring Data Cosmos da tabela acima. Por exemplo, se você estiver usando o Spring Cloud 2022.0.x, deverá usar o Azure Spring Data Cosmos versões 5.3.0 e superior.
Suporte à versão do Spring Data
Este projeto dá suporte a versões spring-data-commons 3.0.x
.
A configuração acima não permite que você substitua dependências individuais usando uma propriedade, conforme explicado acima. Para obter o mesmo resultado, você precisaria adicionar uma entrada na dependencyManagement do projeto antes da entrada spring-boot-dependencies
. Por exemplo, para atualizar para outro treinamento de versão do Spring Data, adicione o item a seguir ao seu 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>
Observação: substitua ${spring.boot.version} e ${spring.data.version} por versões do Spring Boot e do Spring Data que você deseja usar em seu projeto.
Introdução
Incluir o pacote
Caso esteja usando o Maven, adicione a dependência a seguir.
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-spring-data-cosmos</artifactId>
<version>5.6.0</version>
</dependency>
Pré-requisitos
- JDK (Java Development Kit) versão 8 ou posterior.
- Uma conta ativa do Azure. Se não tiver uma, você poderá se inscrever em uma conta gratuita. Como alternativa, você pode usar o Emulador do Azure Cosmos DB para desenvolvimento e teste. Como o certificado https do emulador é autoassinado, você precisa importar seu certificado para o repositório de certificados confiável java, explicado aqui
- (Opcional) SLF4J é uma fachada de registro em log.
- (Opcional) A associação SLF4J é usada para associar uma estrutura de registro em log específica ao SLF4J.
- (Opcional) Maven
O SLF4J só será necessário se você planejar usar o registro em log. Baixe também uma associação SLF4J que vinculará a API SLF4J à implementação do registro em log de sua escolha. Para obter mais informações, confira o Manual do usuário do SLF4J.
Definir classe de configuração
Para definir a classe de configuração, você precisará estender o
AbstractCosmosConfiguration
O Azure-spring-data-cosmos também dá
Response Diagnostics String
suporte a eQuery Metrics
Max Degree of Parallelism
. Defina o sinalizadorqueryMetricsEnabled
como true em application.properties para habilitar as métricas de consulta. Além de definir o sinalizador, implemente oResponseDiagnosticsProcessor
para registrar informações de diagnóstico. DefinamaxDegreeOfParallelism
o sinalizador como um inteiro em application.properties para permitir o processamento paralelo; definir o valor como -1 levará o SDK a decidir o valor ideal. DefinamaxBufferedItemCount
o sinalizador como um inteiro em application.properties para permitir que o usuário defina o número máximo de itens que podem ser armazenados em buffer durante a execução de consulta paralela; se definido como menor que 0, o sistema decide automaticamente o número de itens para buffer. OBSERVAÇÃO: definir isso como um valor muito alto pode resultar em alto consumo de memória. DefinaresponseContinuationTokenLimitInKb
o sinalizador como um inteiro em application.properties para permitir que o usuário limite o comprimento do token de continuação na resposta da consulta. O token de continuação contém campos obrigatórios e opcionais. Os campos necessários são necessários para retomar a execução de onde ela foi interrompida. Os campos opcionais podem conter o trabalho de pesquisa de índice serializado que foi feito, mas ainda não utilizado. Isso evita refazer o trabalho novamente em continuações subsequentes e, portanto, melhorar o desempenho da consulta. Definindo o tamanho máximo de continuação como 1KB, o serviço do Azure Cosmos DB só serializará os campos necessários. A partir de 2KB, o serviço do Azure Cosmos DB seria serializado o máximo que pudesse caber até atingir o tamanho máximo especificado. DefinapointOperationLatencyThresholdInMS
,requestChargeThresholdInRU
nonPointOperationLatencyThresholdInMS
epayloadSizeThresholdInBytes
para habilitar diagnóstico no nível do cliente quando esses limites forem excedidos.
@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);
}
}
}
Personalizando a Configuração
Você pode personalizar DirectConnectionConfig
ou GatewayConnectionConfig
ou ambos e fornecê-los para CosmosClientBuilder
personalizar CosmosAsyncClient
Você pode personalizar pointOperationLatencyThresholdInMS
, requestChargeThresholdInRU
nonPointOperationLatencyThresholdInMS
e payloadSizeThresholdInBytes
personalizar os limites para registro em log de diagnóstico quando combinado com CosmosDiagnosticsHandler
o que permite o registro em log de diagnóstico com os limites padrão quando adicionado ao 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();
}
Por padrão, o @EnableCosmosRepositories
verificará o pacote atual em busca de interfaces que estendam uma das interfaces de repositório do Spring Data.
Use-o para anotar sua classe de Configuração para verificar um pacote raiz diferente pelo @EnableCosmosRepositories(basePackageClass=UserRepository.class)
se o layout do projeto tiver vários projetos.
Habilitar diagnóstico de log para Aplicativo Azure Insights com JavaAgent
O diagnóstico pode ser habilitado passando o JavaAgent com seu aplicativo, como abaixo. Isso habilitará o registro em log com os limites padrão. O '-javaagent' deve ser passado antes do '-jar'.
java -javaagent:"<path-to-applicationinsights-agent-jar>" -jar <myapp.jar>
Usando a taxa de transferência provisionada do banco de dados
O Cosmos dá suporte à taxa de transferência provisionada por contêiner e banco de dados . Por padrão, o spring-data-cosmos provisionará a taxa de transferência para cada contêiner criado. Se preferir compartilhar a taxa de transferência entre contêineres, você poderá habilitar a taxa de transferência provisionada do banco de dados por meio do CosmosConfig.
@Override
public CosmosConfig cosmosConfig() {
int autoscale = false;
int initialRequestUnits = 400;
return CosmosConfig.builder()
.enableDatabaseThroughput(autoscale, initialRequestUnits)
.build();
}
Definir uma entidade
Defina uma entidade simples como item no Azure Cosmos DB.
Você pode definir entidades adicionando a anotação
@Container
e especificando propriedades relacionadas ao contêiner, como o nome do contêiner, as RUs (unidades de solicitação), a vida útil e o contêiner de criação automática.Os contêineres serão criados automaticamente, a menos que você não queira. Defina o
autoCreateContainer
como false na anotação@Container
para desabilitar a criação automática de contêineres.Observação: por padrão, as unidades de solicitação atribuídas a contêineres recém-criados são 400. Especifique um valor de RU diferente para personalizar unidades de solicitação para o contêiner criado pelo SDK (o valor mínimo de 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
O campo será usado como id de item no Azure Cosmos DB. Se você quiser usar outro campo comofirstName
itemid
, basta anotar esse campo com@Id
anotação.A anotação
@Container(containerName="myContainer")
especifica o nome do contêiner no Azure Cosmos DB.A anotação
@PartitionKey
no campolastName
especifica esse campo como a chave de partição no Azure Cosmos DB.
Criando Contêineres com taxa de transferência de dimensionamento automático
- O campo
autoScale
da anotação especifica o contêiner a ser criado com a taxa de transferência de dimensionamento automático, se definido como true. O padrão é false, o que significa que os contêineres são criados com taxa de transferência manual. - Leia mais sobre a taxa de transferência de dimensionamento automático aqui
@Container(containerName = "myContainer", autoScale = true, ru = "4000")
public class UserSample {
@Id
private String emailAddress;
}
Suporte à Chave de Partição Aninhada
- O Azure Spring Data Cosmos dá suporte à chave de partição aninhada. Para adicionar a chave de partição aninhada, use o campo
partitionKeyPath
na anotação@Container
. partitionKeyPath
só deve ser usado para dar suporte ao caminho da chave de partição aninhada. Para suporte geral à chave de partição, use a anotação@PartitionKey
.- Por padrão, a anotação
@PartitionKey
terá precedência, a menos que não seja especificado. - O exemplo abaixo mostra como usar corretamente o recurso chave de Partição Aninhada.
@Container(containerName = "nested-partition-key", partitionKeyPath = "/nestedEntitySample/nestedPartitionKey")
public class NestedPartitionKeyEntitySample {
private NestedEntitySample nestedEntitySample;
}
public class NestedEntitySample {
private String nestedPartitionKey;
}
Criar repositórios
Estende a interface do CosmosRepository, que dá suporte ao repositório do 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);
}
- O método
findByFirstName
é um método de consulta personalizado, ele encontrará itens por firstName.
Cache de plano de consulta
AS APIs de consulta do repositório Spring, como findByFirstName(String firstName)
em que firstName
é a partição ou consultas anotadas que contêm chave de partição, resultarão em um tempo de execução de consulta inferior devido ao cache do plano de consulta. Atualmente, o cache do plano de consulta só tem suporte para métodos de consulta direcionados a uma única partição.
QueryAnnotation: usando consultas anotadas em repositórios
O Azure Spring Data Cosmos dá suporte à especificação de consultas anotadas nos repositórios usando @Query
.
- Exemplos de consultas anotadas no CosmosRepository síncrono:
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);
}
- Exemplos de consultas anotadas no 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);
}
As consultas que são especificadas na anotação são as mesmas que as consultas do cosmos. Confira os artigos a seguir para obter mais informações sobre consultas sql no cosmos
- [Introdução de Consulta de API do Sql] sql_queries_getting_started
- [Tutorial de consulta da API do Sql] sql_queries_in_cosmos
Criar uma Classe de aplicativos
Aqui, crie uma classe de aplicativos com todos os componentes
@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);
}
}
- Interface UserRepository de fio automático, para executar operações como salvar, excluir, encontrar etc.
- O Azure Cosmos DB do Spring Data usa o
CosmosTemplate
e oReactiveCosmosTemplate
para executar as consultas por trás dos métodos encontrar e salvar. Você pode usar o modelo por conta própria para consultas mais complexas.
Principais conceitos
Suporte a CrudRepository e a ReactiveCrudRepository
- O Azure Spring Data Cosmos dá suporte a ReactiveCrudRepository e CrudRepository, que fornece funcionalidade CRUD básica
- Salvar
- findAll
- findOne por Id
- deleteAll
- excluir por ID
- excluir entidade
Anotações do Spring Data
Anotação de @Id do Spring Data
Há duas maneiras de mapear um campo na classe de domínio para o campo id
do Item do Azure Cosmos DB.
- anotar um campo na classe de domínio com
@Id
, esse campo será mapeado para Itemid
no Cosmos DB. - definir o nome desse campo como
id
, esse campo será mapeado para o Itemid
no Azure Cosmos DB.
Geração automática de ID
- Dá suporte à geração automática de UUIDs de tipo de cadeia de caracteres usando a anotação @GeneratedValue. O campo ID de uma entidade com uma ID de tipo de cadeia de caracteres pode ser anotado com
@GeneratedValue
para gerar automaticamente um UUID aleatório antes da inserção.
public class GeneratedIdEntity {
@Id
@GeneratedValue
private String id;
}
Expressão SpEL e Nome de Contêiner Personalizado.
- Por padrão, o nome do contêiner será o nome de classe da classe de domínio de usuário. Para personalizá-lo, adicione a anotação
@Container(containerName="myCustomContainerName")
à classe de domínio. O campo de contêiner também dá suporte a expressões SpEL (por exemplo,container = "${dynamic.container.name}"
oucontainer = "#{@someBean.getContainerName()}"
) para fornecer nomes de contêiner programaticamente/por meio de propriedades de configuração. - Para que as expressões SpEL funcionem corretamente, você precisa adicionar
@DependsOn("expressionResolver")
na parte superior da classe do Spring Application.
@SpringBootApplication
@DependsOn("expressionResolver")
public class SampleApplication {
}
Política de indexação
- Por padrão, IndexingPolicy será definido pelo Serviço do Portal do Azure. Para personalizá-la, adicione a anotação
@CosmosIndexingPolicy
à classe de domínio. Essa anotação tem 5 atributos para personalizar, confira a seguir:
// 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 {};
Política de Chave Exclusiva
- O Azure Spring Data Cosmos dá suporte à configuração
UniqueKeyPolicy
no contêiner adicionando a anotação@CosmosUniqueKeyPolicy
à classe de domínio. Essa anotação tem os seguintes atributos:
@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;
}
Partição do Azure Cosmos DB
- O Azure-spring-data-cosmos dá suporte à partição do Azure Cosmos DB.
- Para especificar um campo de uma classe de domínio como o campo da chave da partição, anote-o com
@PartitionKey
. - Ao executar a operação CRUD, especifique o valor da partição.
- Para obter mais amostras sobre a CRUD de partição, confira o teste aqui
Bloqueio Otimista
- O Azure-spring-data-cosmos dá suporte ao Bloqueio Otimista para contêineres específicos, o que significa que upserts/exclusões por item falharão com uma exceção caso o item seja modificado por outro processo nesse meio tempo.
- Para habilitar o Bloqueio Otimista para um contêiner, basta criar um campo de cadeia de caracteres
_etag
e marcá-lo com a anotação@Version
. Veja o seguinte:
@Container(containerName = "myContainer")
public class MyItem {
String id;
String data;
@Version
String _etag;
}
- Leia mais sobre bloqueio otimista aqui
Consulta personalizada do Spring Data, paginável e classificação
- O Azure-spring-data-cosmos dá suporte a consultas personalizadas do Spring Data
- Por exemplo, operação find, por exemplo,
findByAFieldAndBField
- Dá suporte a Paginável, Fatia e Classificação do Spring Data.
- Com base nas RUs disponíveis na conta do banco de dados, o cosmosDB pode retornar itens menores ou iguais ao tamanho solicitado.
- Devido a esse número variável de itens retornados em cada iteração, o usuário não deve depender do totalPageSize e, em vez disso, a iteração sobre o paginável deve ser feita dessa maneira.
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;
}
Dados Inativos do Iniciador do Spring Boot
- O Azure-spring-data-cosmos dá suporte a spring-boot-starter-data-rest.
- Dá suporte à Lista e ao tipo aninhado na classe de domínio.
- Feijão ObjectMapper configurável com nome
cosmosObjectMapper
exclusivo , configure somente ObjectMapper personalizado se você realmente precisar. Por exemplo,
@Bean(name = "cosmosObjectMapper")
public ObjectMapper objectMapper() {
return new ObjectMapper(); // Do configuration to the ObjectMapper if required
}
Auditoria
- O Azure-spring-data-cosmos dá suporte a campos de auditoria em entidades do banco de dados usando anotações spring-data padrão.
- Esse recurso pode ser habilitado adicionando a anotação
@EnableCosmosAuditing
à configuração do aplicativo. - As entidades podem anotar campos usando
@CreatedBy
,@CreatedDate
,@LastModifiedBy
e@LastModifiedDate
. Esses campos serão atualizados automaticamente.
@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;
}
Configuração de vários bancos de dados
- O Azure-spring-data-cosmos dá suporte à configuração de vários bancos de dados, incluindo "várias contas de banco de dados" e "conta única, com vários bancos de dados".
Contas de vários bancos de dados
O exemplo usa o arquivo 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
A definição de Entidade e Repositório é semelhante à acima. Você pode colocar entidades do banco de dados diferentes em pacotes diferentes.
O usuário de suporte
@EnableReactiveCosmosRepositories
ou@EnableCosmosRepositories
definem o modelo do cosmos, usereactiveCosmosTemplateRef
oucosmosTemplateRef
para configurar o nome do beanReactiveCosmosTemplate
ouCosmosTemplate
a ser usado com os repositórios detectados.Se você tiver várias contas de banco de dados do cosmos, poderá definir vários
CosmosAsyncClient
. Se a única conta do cosmos tiver vários bancos de dados, você poderá usar o mesmoCosmosAsyncClient
para inicializar o modelo do 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);
}
}
}
- No exemplo acima, temos duas contas do Cosmos. Você pode criar o
CosmosAsyncClient
da mesma forma:
@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();
}
- Além disso, se você quiser definir
queryMetricsEnabled
,ResponseDiagnosticsProcessor
,maxDegreeOfParallelism
maxBufferedItemCount
ouresponseContinuationTokenLimitInKb
, poderá criar o para oCosmosConfig
modelo cosmos.
@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
return CosmosConfig.builder()
.enableQueryMetrics(true)
.maxDegreeOfParallelism(0)
.maxBufferedItemCount(0)
.responseContinuationTokenLimitInKb(0)
.responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
.build();
}
- Criar uma Classe de aplicativos
@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();
}
}
Conta única com vários bancos de dados
O exemplo usa o arquivo 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
- A definição de Entidade e Repositório é semelhante à acima. Você pode colocar entidades do banco de dados diferentes em pacotes diferentes.
- Você pode usar o
EnableReactiveCosmosRepositories
com diferentesreactiveCosmosTemplateRef
para definir vários bancos de dados em uma única conta do 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);
}
}
}
- Criar uma Classe de aplicativos
@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();
}
}
Multilocação no nível do banco de dados
- O Azure-spring-data-cosmos dá suporte à multilocação na configuração de nível de banco de dados estendendo
CosmosFactory
e substituindo a função 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();
}
}
Pacote da versão beta
A versão beta criada da ramificação main
está disponível. Você pode conferir a instrução para usar pacotes de versão beta.
Solução de problemas
Geral
Se encontrar algum bug, registre um problema aqui.
Para sugerir um novo recurso ou alterações possíveis, envie um problema da mesma maneira que faria para um bug.
Habilitar o Registro em log do Cliente
- O Azure-spring-data-cosmos usa SLF4j como a fachada de registro em log que dá suporte ao registro em log em estruturas de registro em log populares, como log4j e logback. Por exemplo, se você quiser usar o logback do spring como estrutura de registro em log, adicione o xml a seguir à pasta de recursos.
<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>
Exemplos
- Confira o projeto de exemplo aqui.
Contas de vários bancos de dados
- Confira o projeto de exemplo de Vários Banco de Dados.
Conta única com vários bancos de dados
Próximas etapas
- Leia mais sobre o azure Spring Data Cosmos aqui.
- Leia mais sobre o Serviço do Azure CosmosDB
Contribuição
Este projeto aceita contribuições e sugestões. A maioria das contribuições exige que você concorde com um CLA (Contrato de Licença do Colaborador) declarando que você tem o direito de nos conceder e de fato concede, os direitos de usar sua contribuição.
Quando você envia uma solicitação de pull, um bot do CLA determina automaticamente se você precisa fornecer um CLA e preencher a PR corretamente (por exemplo, rótulo, comentário). Basta seguir as instruções fornecidas pelo bot. Você só precisará fazer isso uma vez em todos os repositórios que usam nosso CLA.
Este projeto adotou o Código de Conduta de Software Livre da Microsoft. Para obter mais informações, confira as Perguntas frequentes sobre o Código de Conduta ou contate opencode@microsoft.com para enviar outras perguntas ou comentários.