Chúng tôi vui mừng thông báo rằng người dùng ứng dụng khách nâng cao dành cho Amazon DynamoDB trong AWS SDK cho Java 2. x giờ đây có thể kích hoạt bộ đếm nguyên tử, cũng như thêm các biểu thức cập nhật DynamoDB tùy chỉnh thông qua khung tiện ích máy khách nâng cao
Khách hàng đã nói với chúng tôi rằng họ muốn cải thiện hiệu suất và tính nhất quán khi cập nhật bản ghi bảng. Quy trình cập nhật bản ghi trong máy khách nâng cao DynamoDB thường có nghĩa là đọc một bản ghi từ cơ sở dữ liệu để truy cập các giá trị hiện tại trước khi ghi lại. Chi phí này có thể gây khó khăn nếu hồ sơ lớn và có thể phát sinh thêm chi phí. Hơn nữa, không có gì đảm bảo rằng bản ghi không được cập nhật giữa lần đọc và lần ghi. Điều này có nghĩa là nó không phải là một tập hợp các hành động nguyên tử
Thay đổi này có nghĩa là bạn có thể gắn thẻ thuộc tính bản ghi số dưới dạng bộ đếm nguyên tử và sử dụng DynamoDB để cập nhật thuộc tính với một giá trị cụ thể mỗi khi bạn gọi thao tác updateItem
trên bảng của mình. Ngoài ra, chúng tôi đã giới thiệu một API mô hình hóa các biểu thức cập nhật. Điều này cho phép bạn viết các tiện ích mở rộng của riêng mình để trực tiếp tạo các biểu thức cập nhật ở cấp lược đồ cho DynamoDB
Các khái niệm
DynamoDB UpdateExpression – Đây là cú pháp được DynamoDB sử dụng khi gọi hoạt động
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
0 của nó. Sử dụng ứng dụng khách DynamoDB nâng cao để tự động tạo biểu thức này khi bạn cung cấp một mục để cập nhậtAPI UpdateExpression ứng dụng khách nâng cao – Đây là bản tóm tắt đại diện cho DynamoDB UpdateExpression trong ứng dụng khách nâng cao. Đọc thêm trong phần Giới thiệu về API UpdateExpression ứng dụng khách nâng cao sau trong bài đăng này
Tiện ích mở rộng máy khách nâng cao – Đây là lớp triển khai giao diện
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
1 nối với logic hoạt động, chẳng hạn như updateItem
và cung cấp khả năng sửa đổi các yêu cầu hoặc tham số phản hồiChuỗi tiện ích mở rộng – Tất cả các tiện ích mở rộng được kích hoạt cho ứng dụng khách nâng cao. Các phần mở rộng trong chuỗi được áp dụng theo thứ tự
Sử dụng bộ đếm nguyên tử
Khi bạn muốn tạo bộ đếm nguyên tử và cập nhật DynamoDB mỗi khi bạn gọi thao tác updateItem
, hãy tạo một thuộc tính bảng thuộc loại
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
4 đại diện cho bộ đếm và gắn thẻ cho nó là bộ đếm nguyên tửBạn kích hoạt chức năng bộ đếm nguyên tử khi khởi tạo ứng dụng khách nâng cao. Điều này là do nó tự động tải tiện ích mở rộng tương ứng,
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
5. Theo mặc định, bộ đếm bắt đầu từ 0 và tăng thêm 1 mỗi khi bản ghi trong bảng được cập nhật. Bạn có thể tùy chỉnh nó bằng cách thay đổi giá trị bắt đầu và/hoặc giá trị gia tăng, bao gồm cả giá trị âmGiá trị bắt đầu được đặt khi
- bạn gọi hoạt động
updateItem
và thuộc tính không tồn tại, hoặc - bạn gọi hoạt động
7static final StaticTableSchema TABLE_SCHEMA= StaticTableSchema.builder[Customer.class] .newItemSupplier[Customer::new] .addAttribute[String.class, a -> a.name["id"] .. ] .addAttribute[Long.class, a -> a.name["defaultCounter"] .getter[Customer::getDefaultCounter] .setter[Customer::setDefaultCounter] .addTag[atomicCounter[]]] .addAttribute[Long.class, a -> a.name["customCounter"] .getter[Customer::getCustomCounter] .setter[Customer::setCustomCounter] .addTag[atomicCounter[5, 10]]] .build[];
Ví dụ sau đây cho thấy cách tạo và sử dụng bộ đếm nguyên tử cho cả lược đồ bảng dựa trên bean và lược đồ bảng tĩnh
Bước 1. Xác định lược đồ với thuộc tính được gắn thẻ
lựa chọn 1. Lược đồ bảng dựa trên Bean
Tạo một thuộc tính thuộc loại Long và chú thích nó bằng
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
8@DynamoDbBean
public class Customer {
@DynamoDbPartitionKey
public String getId[] { .. }
public void setId[String id] { .. }
@DynamoDbAtomicCounter
public Long getUpdateCounter[] { .. }
public void setUpdateCounter[Long counter] { .. }
@DynamoDbAtomicCounter[delta = 5, startValue = 10]
public Long getCustomCounter[] { .. }
public void setCustomCounter[Long counter] { .. }
}
Lựa chọn 2. Lược đồ bảng bất biến tĩnh
Tạo thuộc tính StaticAttribute với loại thuộc tính
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
4 và sử dụng một trong các phương thức DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
0 để gắn thẻ thuộc tínhVí dụ mã sau đây giả định rằng
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
1 tồn tại và định nghĩa một lược đồ để tham chiếu lớpstatic final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
Bước 2. Tạo một khách hàng và tài nguyên bảng
Khởi tạo ứng dụng khách DynamoDB nâng cao và tạo tài nguyên bảng bằng cách cung cấp cho nó lược đồ đã xác định trước đó
________số 8_______Bước 3. Gọi cho DynamoDB
Khởi tạo đối tượng Khách hàng và đặt thuộc tính khóa. Sau đó, gọi updateItem
và
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
3 để xác minh cập nhật tự động của các thuộc tính bộ đếmCustomer customer = Customer.builder[].id["SOME_ID"].build[]:
customerTable.updateItem[customer]; //both putItem and updateItem can be used to add records
Customer retrievedCustomer = customerTable.getItem[customer]
retrievedCustomer.defaultCounter[]; //the value is 0
retrievedCustomer.customCounter[]; //the value is 10
customerTable.updateItem[customer];
retrievedCustomer = customerTable.getItem[customer]
retrievedCustomer.defaultCounter[]; //the value is 1
retrievedCustomer.customCounter[]; //the value is 15
Như bạn có thể thấy, chúng tôi không tham chiếu các thuộc tính trong bản ghi được gửi tới DynamoDB. Tuy nhiên, bản ghi được cập nhật liên tục với các giá trị mỗi khi bạn gọi cơ sở dữ liệu. Đặt giá trị trên bản ghi theo cách thủ công sẽ khiến DynamoDB đưa ra một DynamoDBException, cho biết “Cập nhậtExpression không hợp lệ. Hai đường dẫn tài liệu trùng nhau […]”, bởi vì biểu thức cập nhật với bộ đếm được tạo tự động bởi
static final StaticTableSchema TABLE_SCHEMA=
StaticTableSchema.builder[Customer.class]
.newItemSupplier[Customer::new]
.addAttribute[String.class, a -> a.name["id"] .. ]
.addAttribute[Long.class, a -> a.name["defaultCounter"]
.getter[Customer::getDefaultCounter]
.setter[Customer::setDefaultCounter]
.addTag[atomicCounter[]]]
.addAttribute[Long.class, a -> a.name["customCounter"]
.getter[Customer::getCustomCounter]
.setter[Customer::setCustomCounter]
.addTag[atomicCounter[5, 10]]]
.build[];
5 sẽ xung đột với biểu thức đã được tạo cho chính bản ghi đóTạo tiện ích mở rộng UpdateExpression tùy chỉnh
Viết tiện ích mở rộng của riêng bạn tận dụng tùy chọn mới để cung cấp
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
5 tùy chỉnh trong khung tiện ích mở rộngCập nhật biểu thức trong phần mở rộng có thể áp dụng cho các trường hợp sử dụng mà bạn muốn thực hiện điều tương tự với một thuộc tính mỗi khi bạn gọi cơ sở dữ liệu, chẳng hạn như bộ đếm nguyên tử. Tuy nhiên, nếu bạn cần hiệu ứng một lần cho một yêu cầu, thì việc tận dụng khung tiện ích mở rộng sẽ không hữu ích. Trước khi xem xét hỗ trợ cho biểu thức cập nhật yêu cầu đơn lẻ, chúng tôi sẽ đánh giá việc sử dụng API UpdateExpression mới có trong bản phát hành này, cũng như phản hồi mà chúng tôi nhận được
Giới thiệu về API UpdateExpression ứng dụng khách nâng cao
UpdateExpression ứng dụng khách nâng cao bao gồm một hoặc nhiều UpdateAction tương ứng với cú pháp UpdateExpression của DynamoDB. Trước khi gửi yêu cầu cập nhật tới DynamoDB, máy khách nâng cao sẽ phân tích cú pháp UpdateExpression thành định dạng mà DynamoDB hiểu được
Ví dụ: bạn có thể tạo một RemoveAction sẽ xóa thuộc tính có tên “attr1” khỏi bản ghi
RemoveAction removeAction =
RemoveAction.builder[]
.path["#attr1_ref"]
.putExpressionName["#attr1_ref", "attr1"]
.build[];
Lưu ý rằng, mặc dù việc sử dụng Tên biểu thức là tùy chọn, chúng tôi khuyên bạn nên sử dụng nó để tránh xung đột tên
Bước 1. Tạo một lớp mở rộng
Tạo một lớp mở rộng triển khai hook mở rộng
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
6public final class CustomExtension implements DynamoDbEnhancedClientExtension {
@Override
public WriteModification beforeWrite[DynamoDbExtensionContext.BeforeWrite context] {
return WriteModification.builder[]
.updateExpression[createUpdateExpression[]]
.build[];
}
}
Bạn có thể sử dụng đối tượng bối cảnh để lấy thông tin về những điều sau đây
- Mục đã chuyển đổi
- Siêu dữ liệu bảng, chẳng hạn như thẻ tùy chỉnh
- Tên của hoạt động đang được gọi
Bước 2. Tạo UpdateExpression
Trong tiện ích mở rộng của chúng tôi, SetAction thay đổi giá trị của “attr2”, mà chúng tôi có thể suy ra là thuộc tính Chuỗi
private static UpdateExpression createUpdateExpression[] {
AttributeValue newValue = AttributeValue.builder[].s["A new value"].build[];
SetAction setAction =
SetAction.builder[]
.path["#attr1_ref"]
.value[":new_value"]
.putExpressionName["#attr1_ref", "attr1"]
.putExpressionValue[":new_value", newValue]
.build[];
UpdateExpression.builder[]
.addAction[setAction]
.build[];
}
Bước 3. Thêm tiện ích mở rộng cho khách hàng
Thêm tiện ích mở rộng tùy chỉnh của bạn vào ứng dụng khách
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder[]
.extensions[new CustomExtension[]]]
.build[];
Bước 4. Gọi cho DynamoDB
Truy xuất một tham chiếu đến bảng và gọi updateItem
DynamoDbTable table = enhancedClient.table["tableName", tableSchema];
table.updateItem[new MyRecord[]];
Dưới mui xe
Có thể hữu ích khi hiểu cách hoạt động của khung tiện ích mở rộng và hoạt động UpdateItem để kết hợp đầu ra từ các tiện ích mở rộng với thông tin mục ở cấp độ yêu cầu để tạo thành một yêu cầu DynamoDB gắn kết
- Nếu có một số tiện ích bổ sung thêm UpdateExpressions trong chuỗi tiện ích mở rộng, thì những tiện ích này sẽ được hợp nhất mà không có bất kỳ kiểm tra nào để tạo thành một biểu thức duy nhất
- Mục được cập nhật được cung cấp bởi UpdateItemRequest nâng cao được chuyển đổi bởi thao tác thành một UpdateExpression nội bộ
- UpdateExpression nội bộ trong hoạt động UpdateItem được hợp nhất với một từ khung tiện ích mở rộng – nếu nó tồn tại
- DynamoDB chỉ cho phép một hành động thao tác trên một thuộc tính. Do đó, bất kỳ hành động trùng lặp nào tham chiếu đến cùng một thuộc tính sẽ không thành công cục bộ trong máy khách khi UpdateExpression được phân tích cú pháp thành yêu cầu DynamoDB cấp thấp
- Ứng dụng khách nâng cao tạo các câu lệnh xóa cho bất kỳ thuộc tính nào không được đặt rõ ràng trên một mục được cung cấp cho hoạt động UpdateItem. Vì hành vi mặc định này [được kiểm soát bởi cờ
7] can thiệp vào chức năng của tiện ích mở rộng nên ứng dụng khách sẽ tự động lọc các thuộc tính đó bằng cách kiểm tra xem chúng có xuất hiện trong tiện ích mở rộng UpdateExpression hay không. Nếu có, thì khách hàng không tạo câu lệnh loại bỏ cho họDynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[]; TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
Phần kết luận
Trong bài đăng này, bạn đã học cách sử dụng bộ đếm nguyên tử trong ứng dụng khách DynamoDB nâng cao và bạn đã thấy cách các tiện ích mở rộng có thể hoạt động với API UpdateExpression nâng cao cho các ứng dụng tùy chỉnh. Ứng dụng khách nâng cao là mã nguồn mở và nằm trong cùng một kho lưu trữ với AWS SDK cho Java 2. 0
Chúng tôi hy vọng bạn thấy bài đăng này hữu ích và chúng tôi mong nhận được phản hồi của bạn. Bạn luôn có thể chia sẻ thông tin đầu vào của mình trên trang vấn đề GitHub của chúng tôi hoặc bỏ phiếu ủng hộ các ý tưởng khác cho các tính năng mà bạn muốn thấy trong ứng dụng khách nâng cao DynamoDB hoặc AWS SDK dành cho Java nói chung
Anna-Karin là người duy trì AWS SDK cho Java. Cô ấy có niềm đam mê viết phần mềm và cơ sở hạ tầng có thể bảo trì, cũng như thích làm vườn, đi bộ đường dài và vẽ tranh. Bạn có thể tìm thấy cô ấy trên GitHub @cenedhryn