Java(AWS SDK v2)中的 DynamoDB GetItem

AWS SDK for Java 2.x 把一个项建模成通过不可变构建器组装出来的 Map<String, AttributeValue>。它有两个约定和大多数 SDK 不一样:数字的类型是字符串,而响应里的集合永远不为 null。

请求本身仍然需要完整主键,这一点各处都一样。

代码

import java.util.HashMap;
import java.util.Map;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;

public class GetItemExample {
    public static void main(String[] args) {
        try (DynamoDbClient ddb = DynamoDbClient.builder()
                .region(Region.US_EAST_1)
                .build()) {

            Map<String, AttributeValue> key = new HashMap<>();
            key.put("Artist", AttributeValue.builder().s("Arturo Sandoval").build());
            key.put("SongTitle", AttributeValue.builder().s("Cubano Chant").build());

            Map<String, String> names = new HashMap<>();
            names.put("#proj0", "Artist");
            names.put("#proj1", "SongTitle");
            names.put("#proj2", "AlbumTitle");
            names.put("#proj3", "Year");

            GetItemRequest request = GetItemRequest.builder()
                    .tableName("Music")
                    .key(key)
                    .projectionExpression("#proj0, #proj1, #proj2, #proj3")
                    .expressionAttributeNames(names)
                    .build();

            Map<String, AttributeValue> item = ddb.getItem(request).item();
            if (item.isEmpty()) {
                System.out.println("Item not found");
            } else {
                System.out.println(item);
            }
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
        }
    }
}

说明

  • n() 接收的是 String——AttributeValue.builder().n(1994) 编译不过。Javadoc 给了理由:"Numbers are sent across the network to DynamoDB as strings, to maximize compatibility across languages and libraries." 所以要写成 n("1994"),而回来时的解析也归你。
  • item() 永远不会返回 null——没命中时返回的是一个空 map,所以判断方式是 isEmpty()。要把"服务什么都没返回"和"服务返回了一个空 map"区分开,就调用 hasItem();SDK 会自动构造空集合,而 hasItem() 是唯一能看穿这一点的东西。
  • 它交给你的那个 map 是不可变的——Javadoc 明确说修改它会抛 UnsupportedOperationException。打算改的话,先拷进一个 HashMap
  • 本地没有任何东西会校验别名映射——expressionAttributeNames 就是一个普通的 Map<String, String>。这里 #proj3 是必需的,因为 Year保留字;而声明了却从不引用的别名,是另一种服务端错误:"Value provided in ExpressionAttributeNames unused in expressions"
  • 整个应用共用一个客户端——AWS 说得很直白:"Service clients in the AWS SDK for Java 2.x are thread-safe." try-with-resources 这种写法适合一次性的 main;在长期运行的服务里,请在启动时构建客户端,并且不要每个请求都关一次。
  • .consistentRead(true) 会让读取成本翻倍,而且在 GSI 上会被拒绝。如果你写腻了 AttributeValue 映射,那就用 DynamoDB 增强客户端software.amazon.awssdk.enhanced.dynamodb),它会在这些同样的低层调用之上,把项映射到带注解的 bean 上。

用可视化的方式来做

这次读取到底计 0.5 还是 1 个容量单元,取决于这个项是否装得进 4 KB。项大小计算器会拿这个边界去量你粘进去的项。

DynoTable 把同样的项当作普通行来展示,并把表格背后的查询导出成用这些构建器写成的 Java 程序。下载 DynoTable

相关示例

参考资料

最后核实于 2026-07-28,依据上方链接的 AWS 官方文档。

无需控制台即可使用 DynamoDB

一款快速的 DynamoDB 桌面客户端,可运行 DynamoDB 无法执行的真正 SQL——JOINs、GROUP BY、聚合——并支持可视化编辑和运行在你自己的 Bedrock 密钥上的 AI agent。

30 天免费试用,无需信用卡 — 之后为无时间限制的免费版。