当前位置: 首页 > news >正文

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) 操作

img

需要在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是一个分布式、多分区、基于发布/订阅模式的消息队列&#xff08;Message Queue&#xff09;&#xff0c;具有可扩展和高吞吐率的特点。 kafka中大致包含以下部分&#xff1a; Producer&#xff1a; 消息生产者&#xff0c;向 Kafka Broker 发消息的客户…...

《JavaEE》进程和线程的区别和联系

&#x1f451;作者主页&#xff1a;Java冰激凌 &#x1f4d6;专栏链接&#xff1a;JavaEE 目录 进程是什么&#xff1f; 线程是什么&#xff1f; 进程和线程之间的联系~ ps1&#xff1a;假设我们当前的大兴国际机场有一条登机口可以登入飞机 ps2&#xff1a;我们为…...

Matlab生成sinc信号

Matlab生成sinc信号 在Matlab中生成sinc信号非常容易。首先&#xff0c;我们需要了解什么是sinc波形。 sinc波形是一种理想的信号&#xff0c;它在时域上是一个宽度为无穷的矩形函数&#xff0c;而在频域上则是一个平的频谱。它的公式为&#xff1a; sinc⁡(x)sin⁡(πx)πx\…...

进程与线程区别与联系

进程与线程的区别与联系线程线程介绍为什么要有线程呢?线程与进程的区别于联系(重点)线程 线程介绍 我们知道进程就是运行起来的程序, 那线程又是什么呢? 一个线程就是一个 “执行流”. 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 “同时” 执行着多份代码. …...

使用vbscript.regexp实现VBA代码格式化

Office自带的VBE在编辑代码时&#xff0c;没有自动完成代码缩进的功能&#xff0c;而我们在网上找到的VBA代码&#xff0c;经常没有实现良好的自动缩进&#xff0c;复制到VBE后&#xff0c;可读性较差。本文介绍的宏&#xff0c;通过使用vbscript.regexp对象&#xff0c;利用正…...

选择结构习题:百分值转换成其相应的等级

Description 编一程序&#xff0c;输入一个百分制的成绩(整数类型)&#xff0c;按要求输出相应的字符串信息&#xff0c;对应关系为&#xff1a;     excellent 90-100     good 80-89     middle 70-79     pass 60-69 fail 60以下或100以上 Input 输入仅一行&…...

c# 源生成器

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

[N1CTF 2018]eating_cms1

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

数据结构与算法基础(王卓)(15):KMP算法详解(含速成套路和详细思路剖析)

如果时间不够&#xff0c;急&#xff08;忙&#xff09;着应付考试没心思看&#xff0c;直接参考&#xff08;照抄&#xff09;如下套路&#xff1a; PART 1&#xff1a;关于next [ j ] PPT&#xff1a;P30 根据书上以及视频上给出的思路&#xff08;提醒&#xff09;&#x…...

【互联网架构】聊一聊所谓的“跨语言、跨平台“

文章目录序跨语言跨平台【饭后杂谈】为什么有人说Java的跨平台很鸡肋&#xff1f;序 很多技术都具有跨语言、跨平台的特点 比如JSON是跨语言的、Java是跨平台的、UniAPP、Electron是跨平台的 跨语言和跨平台&#xff0c;是比较重要的一个特性。这些特性经常能够决定开发者是否…...

1.JVM常识之 类加载器

1.jvm组成 JVM组成&#xff1a; 1.类加载器 2.运行时数据区 3.执行引擎 4.本地库接口 各组件的作用&#xff1a; 首先通过类加载器&#xff08;ClassLoader&#xff09;会把 Java 代码转换成字节码&#xff0c;运行时数据区&#xff08;Runtime Data Area&#xff09;再把字节码…...

一天搞定《AI工程师的PySide2 PyQt5实战开发手册》

PySide2/PySide6、PyQt5/PyQt6&#xff1a;都是基于Qt 的Python库&#xff0c;可以形象地这样说&#xff0c;PySide2 是Qt的 亲儿子(Qt官方开发的) &#xff0c; PyQt5 是Qt还没有亲儿子之前的收的 义子 &#xff08;Riverbank Computing这个公司开发的&#xff0c;有商业版权限…...

身份推理桌游

目录 杀人游戏&#xff08;天黑请闭眼&#xff09; &#xff08;1&#xff09;入门版 &#xff08;2&#xff09;标准版 &#xff08;3&#xff09;延伸版——百度百科 &#xff08;3.1&#xff09;引入医生和秘密警察 &#xff08;3.2&#xff09;引入狙击手、森林老人和…...

[LeetCode周赛复盘] 第 99 场双周赛20230304

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

Parcel Bundle漏洞学习

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

RTP载荷H264(实战细节)

RTP包由两部分组成&#xff0c;RTP头和RTP载荷&#xff1a; RTP头 RTP头的 结构如下&#xff1a; 代码结构&#xff1a; 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&#xff1a; GDB - - - (GNU symbolic debugger)是Linux平台下最常用的一款程序调试器。 自己的Linux是否安装GDB? 一般来说&#xff0c;使用Ubuntu的话&#xff0c;系统就会自带的有GDB调试器的 命令窗口输入如下命令可以查看是否安装了gdb&#xff1a; gdb -v …...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...