Azure Cosmos DB Java SDK

azure-cosmos-java
分类通用
作者Agentic Awesome Skills 社区
许可MIT
评分4.90/5
使用13.7K

Azure Cosmos DB Java SDK

适用于 Azure Cosmos DB NoSQL API 的客户端库,支持全球分布和响应式模式。

安装

xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-cosmos</artifactId>
    <version>LATEST</version>
</dependency>

或使用 Azure SDK BOM:

xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-sdk-bom</artifactId>
            <version>{bom_version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-cosmos</artifactId>
</dependency>
</dependencies>

环境变量

bash
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_KEY=<your-primary-key>

身份验证

基于密钥的身份验证

java
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;

CosmosClient client = new CosmosClientBuilder()
.endpoint(System.getenv("COSMOS_ENDPOINT"))
.key(System.getenv("COSMOS_KEY"))
.buildClient();

异步客户端

java
import com.azure.cosmos.CosmosAsyncClient;

CosmosAsyncClient asyncClient = new CosmosClientBuilder()
.endpoint(serviceEndpoint)
.key(key)
.buildAsyncClient();

自定义配置

java
import com.azure.cosmos.ConsistencyLevel;
import java.util.Arrays;

CosmosClient client = new CosmosClientBuilder()
.endpoint(serviceEndpoint)
.key(key)
.directMode(directConnectionConfig, gatewayConnectionConfig)
.consistencyLevel(ConsistencyLevel.SESSION)
.connectionSharingAcrossClientsEnabled(true)
.contentResponseOnWriteEnabled(true)
.userAgentSuffix("my-application")
.preferredRegions(Arrays.asList("West US", "East US"))
.buildClient();

客户端层级

| 类 | 用途 |
|-------|---------|
| CosmosClient / CosmosAsyncClient | 账户级操作 |
| CosmosDatabase / CosmosAsyncDatabase | 数据库操作 |
| CosmosContainer / CosmosAsyncContainer | 容器/项目操作 |

核心工作流

创建数据库

java
// 同步
client.createDatabaseIfNotExists("myDatabase")
    .map(response -> client.getDatabase(response.getProperties().getId()));

// 异步链式调用
asyncClient.createDatabaseIfNotExists("myDatabase")
.map(response -> asyncClient.getDatabase(response.getProperties().getId()))
.subscribe(database -> System.out.println("Created: " + database.getId()));

创建容器

java
asyncClient.createDatabaseIfNotExists("myDatabase")
    .flatMap(dbResponse -> {
        String databaseId = dbResponse.getProperties().getId();
        return asyncClient.getDatabase(databaseId)
            .createContainerIfNotExists("myContainer", "/partitionKey")
            .map(containerResponse -> asyncClient.getDatabase(databaseId)
                .getContainer(containerResponse.getProperties().getId()));
    })
    .subscribe(container -> System.out.println("Container: " + container.getId()));

CRUD 操作

java
import com.azure.cosmos.models.PartitionKey;

CosmosAsy


java
ncContainer container = asyncClient
.getDatabase("myDatabase")
.getContainer("myContainer");

// 创建
container.createItem(new User("1", "John Doe", "[email protected]"))
.flatMap(response -> {
System.out.println("Created: " + response.getItem());
// 读取
return container.readItem(
response.getItem().getId(),
new PartitionKey(response.getItem().getId()),
User.class);
})
.flatMap(response -> {
System.out.println("Read: " + response.getItem());
// 更新
User user = response.getItem();
user.setEmail("[email protected]");
return container.replaceItem(
user,
user.getId(),
new PartitionKey(user.getId()));
})
.flatMap(response -> {
// 删除
return container.deleteItem(
response.getItem().getId(),
new PartitionKey(response.getItem().getId()));
})
.block();

查询文档

java
import com.azure.cosmos.models.CosmosQueryRequestOptions;
import com.azure.cosmos.util.CosmosPagedIterable;

CosmosContainer container = client.getDatabase("myDatabase").getContainer("myContainer");

String query = "SELECT * FROM c WHERE c.status = @status";
CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();

CosmosPagedIterable<User> results = container.queryItems(
query,
options,
User.class
);

results.forEach(user -> System.out.println("User: " + user.getName()));

核心概念

分区键 (Partition Keys)

选择分区键时应考虑:

  • 高基数(具有大量不同值)

  • 数据和请求分布均匀

  • 在查询中频繁使用

一致性级别 (Consistency Levels)

| 级别 | 保证 |
|-------|-----------|
| Strong (强一致性) | 线性一致性 |
| Bounded Staleness (有界陈旧性) | 具有有界延迟的一致前缀 |
| Session (会话一致性) | 会话内的一致前缀 |
| Consistent Prefix (一致前缀) | 读取永远不会看到乱序的写入 |
| Eventual (最终一致性) | 无顺序保证 |

请求单位 (RUs)

所有操作都会消耗 RU。可以通过响应头查看:

java
CosmosItemResponse<User> response = container.createItem(user);
System.out.println("RU charge: " + response.getRequestCharge());

最佳实践

1. 复用 CosmosClient —— 创建一次,在整个应用程序中复用
2. 在高吞吐量场景下使用异步客户端
3. 谨慎选择分区键 —— 这将影响性能和可扩展性
4. 在写入时启用内容响应,以便立即访问创建的项目
5. 为地理分布的应用配置首选区域
6. 使用重试策略处理 429 错误(默认已内置)
7. 在生产环境中使用直接模式 (Direct Mode) 以获得最低延迟

错误处理

java
import com.azure.cosmos.CosmosException;

try {
container.createItem(item);
} catch (CosmosException e) {
System.err.println("Status: " + e.getStatusCode());
System.err.println("Message: " + e.getMessage());
System.err.println("Request charge: " + e.getRequestCharge());

if (e.getStatusCode() == 409) {
System.err.println("Item already exists");
} else if (e.getStatusCode() == 429) {
System.err.println("Rate limited, retry after: " + e.getRetryAfterDuration());
}
}

参考链接

| 资源 | URL |
|----------|-----|
| Maven 包 | https://central.sonatype.com/artifact/com.azure/azure-cosmos |
| API 文档 | https://azuresdkdocs.z19.web.core.windows.net/java/azure-cosmos/latest/index.html |
| 产品文档 | https://learn.microsoft.com/azure/cosmos-db/ |
| 示例代码 | https://github.com/Azure-Samples/azure-cosmos-java-sql-api-samples |
| 性能指南 | https://learn.microsoft.com/azure/cosmos-db/performance-tips-java-sdk-v4-sql |
| 故障排除 | https://learn.microsoft.com/azure/cosmos-db/troubleshoot-java-sdk-v4-sql |

使用场景

本技能适用于执行概览中所描述的工作流或操作。

局限性

  • 仅在任务与上述范围明确匹配时使用此技能。
  • 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止操作并寻求澄清。