AWS之Amazon DynamoDB用法详解

说明

       最近公司开始用aws的一些服务了,因此有必要学习一下aws的一些知识。但aws的开发文档貌似对新手不太友好的样子,而网上的知识又太多太杂,筛选知识需耗费一定时间,且照着文档敲完,过段时间又会忘记。因此,有必要总结一下一些关于DDB的操作,以便自己实时的学习,也希望自己写的blog能够帮助到别人。

什么是DynamoDB?

       Amazon DynamoDB 是一种完全托管的 NoSQL 数据库服务,提供快速且可预测的性能,同时还能够实现无缝扩展。同时,DynamoDB 会自动将您的表的数据和流量分散到足够数量的服务器上,以满足您的吞吐量和存储需求,同时保持始终如一的高性能。
  简单来说,DDB就是AWS提供的一个NoSql数据库

DynamoDB核心组件

  • 表 Table:和其他类型的数据库差不多,相当于所有数据的集合。
  • 项目 Item:每一条Item就是表中的一条数据。
  • 主键 PriamryKey:
    • 分区键,创建表时必须要有的字段,用来确定表中数据的唯一性。
    • 排序键,创建表时可选可不选,可理解为二级主键 。当两条项目有相同的分区键时,必须要有不同的排序键区分它们。
  • 属性 Attributes:项目的字段名,如user中,name,gender,age为字段名。

使用DDB前的一些配置

1.首先需要有aws的账户,接着获取访问密钥,配置凭证等等。个人可以注册国外账户,国内目前好像只有企业用户才能申请。设置DynamoDB

2.控制台创建一张user表用作示例

user_iddateagenamegenderhobby
123452019-01-0520Sakura1[ { “type” : “sing”}, {“type” : “walk”} ]


3.接着开始代码,先是maven的导入

<dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.11.683</version>
</dependency>

4.自己写的DBUtils

public class DBUtils {

    static String endPoint = "endpoint";
    static String region = "region";
    static String tableName = "tableName";

    public static AmazonDynamoDB getClient() {
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, region))
                .build();
        return client;
    }
	
	//后面主要table用的多
    public static Table getTable() {
        AmazonDynamoDB client = getClient();
        DynamoDB dynamoDB = new DynamoDB(client);
        return dynamoDB.getTable(tableName);
    }
}

DynamoDB的create

1.newItem添加记录

public void createItem() {
        String userId = "123456";
        String date = "2020-01-05";
        String name = "Sakura";
        String age = "20";
        String gender = "1";
        List<Map> hobby = new ArrayList<>();
        Map<String, String> map1 = new HashMap<>();
        Map<String, String> map2 = new HashMap<>();
        map1.put("type", "sing");
        map2.put("type", "walk");
        hobby.add(map1);
        hobby.add(map2);

        Item item = new Item().withPrimaryKey("user_id", userId,"date",date)
                .withString("name", name)
                .withString("age", age)
                .withString("gender", gender).withList("hobby",hobby);

        table.putItem(item);
    }

2.根据mapper映射添加

@Data、@AllArgsConstructor、@NoArgsConstructor为Lombok插件带的注解。
@DynamoDBTable注解值为表名,@DynamoDBHashKey为主键,@DynamoDBAttribute为字段属性。

public void createItemByMapper(){
        List<Map> hobby = new ArrayList<>();
        User user = new User("12345", "2020-01-05", "Sakura", "20", "1", hobby);

        AmazonDynamoDB client = DBUtils.getClient();
        DynamoDBMapper mapper = new DynamoDBMapper(client);

        mapper.save(user);
    }

DynamoDB的update

1.根据spec更新项目

       UpdateExpression为更新表达式,一般格式为 set #字段名 = :修改值,具体好像是因为aws存有一些保留字会冲突啥的,因此用#代表占位符,所以更新表达式中需用变量替换表中的字段名。
  NameMap为更新表达式中你所表示的字段的名称,如示例中,#name代表的就是表中name这个字段。
  ValueMap为更新表达式中你所要更新的值,如:val的值为nameVal,冒号(:)也代表占位符,就表示将表中name这个字段的值改为nameVal。
  最后ReturnValues为枚举类,有NONE,ALL_OLD,UPDATED_OLD,ALL_NEW,UPDATED_NEW五个,具体啥区别我目前也还没弄清,知道的望评论help me解惑一下,谢谢!

public void updateItemBySpec() {
        String userId = "12345";
        String date = "2020-01-05";

        //要修改的值
        String nameVal = "Jack";
        List<Map> hobby = new ArrayList<>();

        UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("user_id", userId, "date", date)
                .withUpdateExpression("set #name = :val1 , #hobby = :hobby")
                .withNameMap(new NameMap().with("#name", "name").with("#hobby", "hobby"))
                .withValueMap(new ValueMap().with(":val1", nameVal).withList(":hobby", hobby))
                .withReturnValues(ReturnValue.UPDATED_NEW);

        table.updateItem(updateItemSpec);
    }

2.根据spec有条件更新Item

       如下示例中,当hoby的数量小于10时,将name的值(Sakura)改为Tony,具体条件表达式写在ConditionExpression中。

public void updateItemBySpecCondition() {
        String userId = "123456";
        String date = "2020-01-05";
		//要更新的值
        String nameVal = "Tony";

        UpdateItemSpec spec = new UpdateItemSpec().withPrimaryKey("user_id", userId, "date", date)
                .withUpdateExpression("set #name = :val1")
                .withConditionExpression("size(hobby) < :num")
                .withNameMap(new NameMap().with("#name", "name"))
                .withValueMap(new ValueMap().with(":val1", nameVal).withNumber(":num", 10))
                .withReturnValues(ReturnValue.UPDATED_NEW);

        table.updateItem(spec);
    }

DynamoDB的retrieve

1. 根据主键读取项目

       其中,user_id为该表分区键,date为排序键(如果有的话),name、age、gender为该表的字段。
需要查询哪些字段,可直接在getItem后用逗号拼上需查询的字段名。

public void retrieveItemByPrimaryKey() {
	String userId = "12345";
	Item item = table.getItem("user_id", userId, "name,age,gender", null);
	//如果该表有排序键时需改为:
	//Item item = table.getItem("user_id", userId, "date", date,"name,age,gender",null);
    }

2.根据spec读取项目

public void retrieveItemBySpec(){
        String userId = "12345";
        String date = "2020-01-05";

        GetItemSpec getItemSpec = new GetItemSpec()
                .withPrimaryKey("user_id", userId, "date", date)
                .withAttributesToGet("name", "gender", "age");

        Item item = table.getItem(getItemSpec);
    }

DynamoDB的delete

       删除一般用的比较少,慎用,一不小心就可能要跑路的样子。

1.根据主键删除项目

public void deleteItemByPrimaryKey() {
        String userId = "12345";
        String date = "2020-01-05";

        table.deleteItem("user_id", userId, "date", date);
    }

2.根据spec删除项目

       删除项目也可以用到表达式,示例中,当hobby的长度小于10时,删除该条记录,否则,会直接报异常
即:如果:num那改为1,hobby实际长度为2,执行此方法则会报异常信息。因此,实际使用时可能需要手动try catch。

public void deleteItemBySpec(){
        String userId = "12345";
        String date = "2020-01-05";

        DeleteItemSpec spec = new DeleteItemSpec().withPrimaryKey("user_id", userId, "date", date)
                .withConditionExpression("size(hobby) < :num")
                .withValueMap(new ValueMap().with(":num", 10));

        table.deleteItem(spec);
    }

附:Item 的一些方法调用

       一般数据传输用的都是json格式,如果Item直接输出的话,格式不是我们想要的:

System.out.println(item);

{ Item: {date=2020-01-05, gender=1, user_id=12345, name=Sakura, age=20, hobby=[{type=sing}, {type=walk}]} }

       因此拿到item后还需做些转化:

  • item.asMap(),将item转化为map格式:
Map<String, Object> map = item.asMap();
System.out.println(map);

{date=2020-01-05, gender=1, user_id=12345, name=Sakura, age=20, hobby=[{type=sing}, {type=walk}]}
  • item.getList(“hobby”),获取对应的list
List<Map> hobby = item.getList("hobby");
System.out.println(hobby);

[{type=sing}, {type=walk}]
  • item.getJSON(“hobby”),直接获取json数据
String json = item.getJSON("hobby");
System.out.println(json);

[{"type":"sing"},{"type":"walk"}]

       第一次写blog,可能会有许多不足之处,有些地方还没写到(如二级索引等,毕竟自己也没弄明白)欢迎大家指正。谢谢大家的阅读,有问题的话大家一起讨论,下面附awsDDB官方文档供查阅。谢谢~~~

awsDynamoDB官方文档

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值