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 …...

Vim一次复制,多次粘贴
我们平常在使用Vim时候,通过viwy或者yy等复制操作之后,p操作粘贴的时候,只能粘贴一次,想要粘贴多次怎么办? 解决方案:在使用p的是时候使用"0p,这样就能无限制的一直粘贴了。 可是ÿ…...

如何修改Win11上的默认程序?
在Win10之前,更改特定文件格式的默认程序很简单,但在Win11发布之后,很多用户都不清楚关于Win11的修改默认程序的操作步骤,接下来我们就一起来看看吧,希望可以帮助到大家。 步骤如下: 一、如何更改Windows 1…...

安装Linux虚拟机和Hadoop平台教程汇总及踩坑总结
📍主要内容介绍安装Linux虚拟机、ubuntu系统、安装hadoop三个环节的教程链接介绍及本机与虚拟机的FTP传输教程总结(直接找hadoop安装环节的5.filezilla传输文件)新鲜出炉的踩坑总结和填坑指南安装Linux虚拟机和ubuntu系统一、材料和工具1、下…...

Shell脚本的使用和介绍
为了方便以后工作使用和复习,吐血整理记录一下学习shell脚本的笔记,看这篇文章需要对linux系统熟悉,希望对大家有所帮助! 文章目录 目录 文章目录 一、什么是shell? 为什么要学习和使用shell? 二、shell的分类...

机械学习 - 基础概念 - scikit-learn - 数据预处理 - 1
目录安装 scikit-learn术语理解1. 特征(feature )和样本( sample / demo)的区别?2. 关于模型的概念一、机械学习概念1. 监督学习总结:2. 非监督学习总结:3. 强化学习总结:三种学习的…...

OLCNE cluster 配置 NFS Storage(英文)
OLCNE cluster 配置 NFS Storage(英文)Create an OLCNE cluster.Create an NFS server.a. Install the NFS utility package on the server and client instances.b. Create a directory for your shared files. Make sure that the server does not hav…...

RabbitMQ高级特性
RabbitMQ高级特性 消息可靠性投递 Consumer ACK 消费端限流 TTL 死信队列 延迟队列 日志与监控 消息可靠性分析与追踪 管理 消息可靠性投递 在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。RabbitMQ 为我们提供了两种方式用来控制…...

利用Dockerfile开发定制镜像实战.
Dockerfile的原理 dockerfile是一种文本格式的文件,用于描述如何构建Docker镜像。在Dockerfile中,我们可以定义基础镜像、安装依赖、添加文件等操作,最终生成一个可以直接运行的容器镜像。 Dockerfile的原理可以分为以下几个步骤:…...

PyInstaller 将DLL文件打包进exe
PyInstaller 将DLL文件打包进exe方法1:通过--add-data命令方法2:通过修改 .spec扩展:博主热门文章推荐:方法1:通过–add-data命令 注意:这里 dll末尾添加的.为当前目录,则该dll要放到main.py同一…...

【JVM篇2】垃圾回收机制
目录 一、GC的作用 申请变量的时机&销毁变量的时机 内存泄漏 内存溢出(oom) 垃圾回收的劣势 二、GC的工作过程 回收垃圾的过程 第一阶段:找垃圾/判定垃圾 方案1:基于引用计数(非Java语言) 引用计数方式的缺陷 方案2:可达性分析…...