aws dynamodb java低等级api和高级客户端api的使用
参考资料
- https://docs.amazonaws.cn/zh_cn/sdk-for-java/latest/developer-guide/setup-project-maven.html
初始化环境
创建maven项目
mvn org.apache.maven.plugins:maven-archetype-plugin:3.1.2:generate \-DarchetypeArtifactId="maven-archetype-quickstart" \-DarchetypeGroupId="org.apache.maven.archetypes" \-DarchetypeVersion="1.4" \-DgroupId="com.zhojiew.myapp" \-DartifactId="ddbapp"
加载依赖
https://mvnrepository.com/artifact/software.amazon.awssdk/bom/latest
配置maven依赖
<project><dependencyManagement><dependencies><dependency><groupId>software.amazon.awssdk</groupId><artifactId>bom</artifactId><version>2.20.21</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>software.amazon.awssdk</groupId><artifactId>dynamodb</artifactId></dependency><dependency><groupId>software.amazon.awssdk</groupId><artifactId>dynamodb-enhanced</artifactId></dependency></dependencies>...
</project>
java低级api操作
官方文档和示例仓库中有非常详细的样例,例如以下创建删除表,注意流程如下
- 初始化区域和凭证
- 初始化ddb客户端
- 构造请求参数
- 发送请求接受响应
// 初始化客户端
Region region = Region.CN_NORTH_1;
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
DynamoDbClient ddb = DynamoDbClient.builder().region(region).build();DynamoDbWaiter dbWaiter = ddb.waiter(); //初始化ddb客户端请求,创建复合主键表
CreateTableRequest request = CreateTableRequest.builder() //设置属性字段 .attributeDefinitions( AttributeDefinition.builder().attributeName(keypart).attributeType(ScalarAttributeType.S).build(), AttributeDefinition.builder().attributeName(keyrange).attributeType(ScalarAttributeType.S).build() ) // 指定分区和排序键.keySchema( KeySchemaElement.builder().attributeName(keypart).keyType(KeyType.HASH).build(), KeySchemaElement.builder().attributeName(keyrange).keyType(KeyType.RANGE).build() ) // 预置读写容量5.provisionedThroughput(ProvisionedThroughput.builder() .readCapacityUnits(new Long(5)) .writeCapacityUnits(new Long(5)) .build()) .tableName(tableName) .build(); // 返回值
String newTable = ""; try { // 创建表CreateTableResponse response = ddb.createTable(request); DescribeTableRequest tableRequest = DescribeTableRequest.builder() .tableName(tableName) .build(); // 等待请求返回WaiterResponse<DescribeTableResponse> waiterResponse = dbWaiter.waitUntilTableExists(tableRequest); waiterResponse.matched().response().ifPresent(System.out::println); newTable = response.tableDescription().tableName(); return newTable; } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1);
}// 初始化删除请求
DeleteTableRequest request = DeleteTableRequest.builder() .tableName("ThreeKingdoms") .build();
// 删除表
try { ddb.deleteTable(request);
} catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1);
}
查询item(同步)
public static void getDynamoDBItem(DynamoDbClient ddb,String tableName,String key,String keyVal ) {HashMap<String,AttributeValue> keyToGet = new HashMap<String,AttributeValue>();// 初始化键参数keyToGet.put(key, AttributeValue.builder().s(keyVal).build());// 构造请求GetItemRequest request = GetItemRequest.builder().key(keyToGet).tableName(tableName).build();try {Map<String,AttributeValue> returnedItem = ddb.getItem(request).item();// 输出itemif (returnedItem != null) {Set<String> keys = returnedItem.keySet();System.out.println("Amazon DynamoDB table attributes: \n");for (String key1 : keys) {System.out.format("%s: %s\n", key1, returnedItem.get(key1).toString());}} else {System.out.format("No item found with the key %s!\n", key);}} catch (DynamoDbException e) {System.err.println(e.getMessage());System.exit(1);}}
插入item
public static void putItemInTable(DynamoDbClient ddb,String tableName,String key,String keyVal,String albumTitle,String albumTitleValue,String awards,String awardVal,String songTitle,String songTitleVal){HashMap<String,AttributeValue> itemValues = new HashMap<String,AttributeValue>();// 构造itemitemValues.put(key, AttributeValue.builder().s(keyVal).build());itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build());itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build());itemValues.put(awards, AttributeValue.builder().s(awardVal).build());// 给否在请求PutItemRequest request = PutItemRequest.builder().tableName(tableName).item(itemValues).build();try {ddb.putItem(request);System.out.println(tableName +" was successfully updated");} catch (ResourceNotFoundException e) {...略}}
从以上的流程可知,低等级的api需要手动构造请求参数和发送请求,属于一种过程式的客户端。用户需要控制请求的具体参数,实际上就是awscli的java版本调用
- 对于创建表来说,需要指定表名,键名,读写容量等。
- 对于item的操作会更复杂,需要手动构造item的请求,尽管有batch操作的api仍旧较为繁琐。
java高级api操作
我们主要来看java的高级api操作
https://docs.amazonaws.cn/zh_cn/sdk-for-java/latest/developer-guide/examples-dynamodb-enhanced.html
DynamoDB 增强版客户端是一个高级库,是Amazon SDK for Java版本 2 (v2) 的一部分。它提供一种将客户端类映射到 DynamoDB 表的直接方法。您可以在代码中定义表与其相应模型类之间的关系。定义这些关系后,您可以直观地对 DynamoDB 中的表或项目执行各种创建、读取、更新或删除 (CRUD) 操作
需要在java项目中额外导入依赖
<dependency><groupId>software.amazon.awssdk</groupId><artifactId>dynamodb-enhanced</artifactId>
</dependency>
DynamoDbEnhancedClient实例用于处理 DynamoDB 表和映射类。DynamoDbEnhancedClient
从现有DynamoDbClient
对象创建
之前接触过一些SSM和SSH框架,有点类似与hibernate的DAO映射,通过注解完成POJO和item的映射,用户就不需要写CRUD操作了,更像是一种声明式的写法。
第一步生成TableSchema
- v2的java sdk包括一组注解用来快速生成
TableSchema
用于将类映射到表的注释 - 例如以下POJO,注解指定了分区键和排序键
@DynamoDbBean
public class Customer { private String id; private String name; private String email; private Instant regDate; @DynamoDbPartitionKey public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getCustName() { return this.name; } public void setCustName(String name) { this.name = name; } @DynamoDbSortKey public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } public Instant getRegistrationDate() { return regDate; } public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; } @Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", regDate=" + regDate + "]"; }
}
创建表
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/enhanced/EnhancedCreateTable.java
public static void main(String[] args) { // 初始化客户端DynamoDbClient ddb = DynamoDbClient.builder().region(Region.CN_NORTH_1).build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build(); // 从Bean tableschema创建表请求DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); // 创建表customerTable.createTable(builder -> builder .provisionedThroughput(b -> b .readCapacityUnits(5L) .writeCapacityUnits(5L) .build()) ); System.out.println("Waiting for table creation..."); // 等待表创建,获取响应try (DynamoDbWaiter waiter = DynamoDbWaiter.create()) { ResponseOrException<DescribeTableResponse> response = waiter .waitUntilTableExists(builder -> builder.tableName("Customer").build()) .matched(); DescribeTableResponse tableDescription = response.response().orElseThrow( () -> new RuntimeException("Customer table was not created.")); System.out.println(tableDescription.table().tableName() + " was created."); }
}
控制台查看表创建结果
- 默认情况下,类名和表名一致
- 字段名和键名一致
再来看看item的相关示例
- 此时我们只需要构造实例,然后使用高级客户端插入item即可
- 比起低级api开发效率更高了
DynamoDbClient ddb = DynamoDbClient.builder().region(Region.CN_NORTH_1).build();
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(ddb) .build();
try { DynamoDbTable<Customer> custTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class)); // 构造item LocalDate localDate = LocalDate.parse("2020-04-07"); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant instant = localDateTime.toInstant(ZoneOffset.UTC); Customer custRecord = new Customer(); custRecord.setCustName("Tom red"); custRecord.setId("id101"); custRecord.setEmail("tred@noserver.com"); custRecord.setRegistrationDate(instant); // 在表中插入itemcustTable.putItem(custRecord); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1);
}
查看item插入成功
rust低级api操作
不得不说,java低级api的写法有点繁琐,对比下rust看看
创建表
说实话下面的这段代码咱只能看懂和java类似的部分,至于tokio和strucopt看不太懂,需要继续学习下rust,现在先抄着用吧
$ cat Cargo.toml
[package]
name = "rustdemo"
version = "0.1.0"
edition = "2021"[dependencies]
aws-config = "0.54.1"
aws-sdk-dynamodb = "0.24.0"
structopt = "0.3.26"
tokio = { version = "1.26.0", features = ["full"] }
tracing-subscriber = "0.3.16"
话说就这一点东西debug编译之后有187M,而release只有17M
use aws_sdk_dynamodb::{model::{AttributeDefinition, KeySchemaElement, KeyType, ProvisionedThroughput, ScalarAttributeType,},Client, Error,
};
use aws_config::meta::region::RegionProviderChain;
use aws_sdk_dynamodb::{ Region, PKG_VERSION};
use structopt::StructOpt;#[derive(Debug, StructOpt)]
struct Opt {/// The AWS Region.#[structopt(short, long)]region: Option<String>,/// Whether to display additional information.#[structopt(short, long)]verbose: bool,
}#[tokio::main]
async fn main() -> Result<(), Error> {tracing_subscriber::fmt::init();let Opt { region, verbose } = Opt::from_args();let region_provider = RegionProviderChain::first_try(region.map(Region::new)).or_default_provider().or_else(Region::new("cn-north-1"));println!();if verbose {println!("DynamoDB client version: {}", PKG_VERSION);println!("Region: {}",region_provider.region().await.unwrap().as_ref());println!();}let shared_config = aws_config::from_env().region(region_provider).load().await;let client = Client::new(&shared_config);list_tables(&client).await?;create_table(&client).await
}async fn list_tables(client: &Client) -> Result<(), Error> {let tables = client.list_tables().send().await?;println!("Current DynamoDB tables: {:?}", tables);Ok(())
}async fn create_table(client: &Client) -> Result<(), Error> {let new_table = client.create_table().table_name("test-table").key_schema(KeySchemaElement::builder().attribute_name("k").key_type(KeyType::Hash).build(),).attribute_definitions(AttributeDefinition::builder().attribute_name("k").attribute_type(ScalarAttributeType::S).build(),).provisioned_throughput(ProvisionedThroughput::builder().write_capacity_units(5).read_capacity_units(5).build(),).send().await?;println!("new table: {:#?}",&new_table.table_description().unwrap().table_arn().unwrap());Ok(())
}
执行试试
$ ./rustdemo
2023-03-11T11:22:12.870149Z INFO aws_credential_types::cache::lazy_caching: credentials cache miss occurred; retrieved new AWS credentials (took 7.115433ms)
Current DynamoDB tables: ListTablesOutput { table_names: Some(["AppSyncCommentTable-JiXcP7eW", "AppSyncEventTable-JiXcP7eW", "Music", "http-crud-tutorial-items", "learnddb"]), last_evaluated_table_name: None }
new table: "arn:aws-cn:dynamodb:cn-north-1:xxxxxxxxxxx:table/test-table"
总结一下
-
api的使用就是照着文档抄没什么好说的,毕竟是不开源的东西会用就行,最重要的还是理解不同层次的api的区别
-
之后可以将ayysync,dynamodb和apigateway集成看看有什么火花
相关文章:

aws dynamodb java低等级api和高级客户端api的使用
参考资料 https://docs.amazonaws.cn/zh_cn/sdk-for-java/latest/developer-guide/setup-project-maven.html 初始化环境 创建maven项目 mvn org.apache.maven.plugins:maven-archetype-plugin:3.1.2:generate \-DarchetypeArtifactId"maven-archetype-quickstart&quo…...

Kafka中那些巧妙的设计
一、kafka的架构 Kafka是一个分布式、多分区、基于发布/订阅模式的消息队列(Message Queue),具有可扩展和高吞吐率的特点。 kafka中大致包含以下部分: Producer: 消息生产者,向 Kafka Broker 发消息的客户…...

《JavaEE》进程和线程的区别和联系
👑作者主页:Java冰激凌 📖专栏链接:JavaEE 目录 进程是什么? 线程是什么? 进程和线程之间的联系~ ps1:假设我们当前的大兴国际机场有一条登机口可以登入飞机 ps2:我们为…...

Matlab生成sinc信号
Matlab生成sinc信号 在Matlab中生成sinc信号非常容易。首先,我们需要了解什么是sinc波形。 sinc波形是一种理想的信号,它在时域上是一个宽度为无穷的矩形函数,而在频域上则是一个平的频谱。它的公式为: sinc(x)sin(πx)πx\…...
进程与线程区别与联系
进程与线程的区别与联系线程线程介绍为什么要有线程呢?线程与进程的区别于联系(重点)线程 线程介绍 我们知道进程就是运行起来的程序, 那线程又是什么呢? 一个线程就是一个 “执行流”. 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 “同时” 执行着多份代码. …...
使用vbscript.regexp实现VBA代码格式化
Office自带的VBE在编辑代码时,没有自动完成代码缩进的功能,而我们在网上找到的VBA代码,经常没有实现良好的自动缩进,复制到VBE后,可读性较差。本文介绍的宏,通过使用vbscript.regexp对象,利用正…...
选择结构习题:百分值转换成其相应的等级
Description 编一程序,输入一个百分制的成绩(整数类型),按要求输出相应的字符串信息,对应关系为: excellent 90-100 good 80-89 middle 70-79 pass 60-69 fail 60以下或100以上 Input 输入仅一行&…...

c# 源生成器
本文概述了 .NET Compiler Platform(“Roslyn”)SDK 附带的源生成器。 通过源生成器,C# 开发人员可以在编译用户代码时检查用户代码。 生成器可以动态创建新的 C# 源文件,这些文件将添加到用户的编译中。 这样,代码可以…...

[N1CTF 2018]eating_cms1
一个cms,先打开环境试了一下弱口令,无效,再试一下万能密码,告诉我有waf,先不想怎么绕过,直接开扫(信息收集)访问register.php注册一个账号进行登录上面的链接尝试用php读文件http://…...

数据结构与算法基础(王卓)(15):KMP算法详解(含速成套路和详细思路剖析)
如果时间不够,急(忙)着应付考试没心思看,直接参考(照抄)如下套路: PART 1:关于next [ j ] PPT:P30 根据书上以及视频上给出的思路(提醒)&#x…...

【互联网架构】聊一聊所谓的“跨语言、跨平台“
文章目录序跨语言跨平台【饭后杂谈】为什么有人说Java的跨平台很鸡肋?序 很多技术都具有跨语言、跨平台的特点 比如JSON是跨语言的、Java是跨平台的、UniAPP、Electron是跨平台的 跨语言和跨平台,是比较重要的一个特性。这些特性经常能够决定开发者是否…...

1.JVM常识之 类加载器
1.jvm组成 JVM组成: 1.类加载器 2.运行时数据区 3.执行引擎 4.本地库接口 各组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码…...

一天搞定《AI工程师的PySide2 PyQt5实战开发手册》
PySide2/PySide6、PyQt5/PyQt6:都是基于Qt 的Python库,可以形象地这样说,PySide2 是Qt的 亲儿子(Qt官方开发的) , PyQt5 是Qt还没有亲儿子之前的收的 义子 (Riverbank Computing这个公司开发的,有商业版权限…...

身份推理桌游
目录 杀人游戏(天黑请闭眼) (1)入门版 (2)标准版 (3)延伸版——百度百科 (3.1)引入医生和秘密警察 (3.2)引入狙击手、森林老人和…...

[LeetCode周赛复盘] 第 99 场双周赛20230304
[LeetCode周赛复盘] 第 99 场双周赛20230304 一、本周周赛总结二、 [Easy] 2578. 最小和分割1. 题目描述2. 思路分析3. 代码实现三、[Medium] 2579. 统计染色格子数1. 题目描述2. 思路分析3. 代码实现四、[Medium] 2580. 统计将重叠区间合并成组的方案数1. 题目描述2. 思路分析…...

Parcel Bundle漏洞学习
Bundle的序列化细节看上去还是有些复杂的,在之前已经讨论过,一般我们使用Parcel的时候,都是严格的write和read相对应。一些疏漏,不对应,竟然就可以成为漏洞,https://xz.aliyun.com/t/2364 里介绍了Bundle漏…...

RTP载荷H264(实战细节)
RTP包由两部分组成,RTP头和RTP载荷: RTP头 RTP头的 结构如下: 代码结构: typedef struct RtpHdr {uint8_t cc : 4, // CSRC countx : 1, // header extendp : 1, // padding flagversion : 2; // versionuint8_t …...
软考高级信息系统项目管理师系列之四十三:信息系统安全管理
软考高级信息系统项目管理师系列之四十三:信息系统安全管理 一、信息系统安全管理内容二、信息安全策略1.信息系统安全策略的概念与内容2.信息系统安全等级保护的概念三、信息安全系统1.信息安全系统三维空间2.信息安全系统三种架构体系四、PKI公开密钥基础设施1.PKI总体架构2…...

并发编程之AtomicUnsafe
目录 原子操作 定义 术语 处理器如何实现原子操作 处理器自动保证基本内存操作的原子性 使用总线锁保证原子性 使用缓存锁保证原子性 Java当中如何实现原子操作 Atomic 定义 原子更新基本类型类 原子更新数组类 原子更新引用类型 原子更新字段类 Unsafe应用解析…...

GDB调试快速入门
什么是GDB: GDB - - - (GNU symbolic debugger)是Linux平台下最常用的一款程序调试器。 自己的Linux是否安装GDB? 一般来说,使用Ubuntu的话,系统就会自带的有GDB调试器的 命令窗口输入如下命令可以查看是否安装了gdb: gdb -v …...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...