DynamoDBMapper 클래스 - Amazon DynamoDB

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

DynamoDBMapper 클래스

DynamoDBMapper 클래스는 Amazon DynamoDB API의 진입점입니다. DynamoDB 엔드포인트에 액세스하고 여러 테이블의 데이터에 액세스할 수 있습니다. 또한 항목에 대한 다양한 생성, 읽기, 업데이트 및 삭제(CRUD) 작업을 수행하고 테이블에 대한 쿼리 및 스캔을 실행할 수 있습니다. 이 클래스는 DynamoDB를 작업하기 위한 다음과 같은 메서드를 제공합니다.

해당 Javadoc 설명서는 AWS SDK for Java API 참조DynamoDBMapper를 참조하세요.

저장

지정한 객체를 테이블에 저장합니다. 여기서 저장하는 객체가 이 메서드에 유일하게 필요한 파라미터입니다. DynamoDBMapperConfig 객체를 사용하여 옵션으로 구성 파라미터를 입력할 수도 있습니다.

동일한 기본 키를 사용하는 항목이 없을 경우에는 이 메서드가 테이블에 새로운 항목을 생성합니다. 그리고, 동일한 기본 키를 사용하는 항목이 있을 경우에는 기존 항목을 업데이트합니다. 파티션 키와 정렬 키가 String 형식이고 @DynamoDBAutoGeneratedKey로 주석된 경우 초기화되지 않았으면 랜덤 UUID(Universally Unique Identifier)가 부여됩니다. @DynamoDBVersionAttribute 주석이 추가된 버전 필드는 1씩 증가합니다. 또한 버전 필드를 업데이트하거나 키를 생성하는 경우 작업 결과에 따라 전달되는 객체도 업데이트됩니다.

기본적으로 매핑된 클래스 속성에 해당되는 속성만 업데이트됩니다. 항목의 기존 추가 속성은 영향을 받지 않습니다. 하지만 SaveBehavior.CLOBBER를 지정할 경우 항목을 강제로 완전히 덮어쓸 수 있습니다.

DynamoDBMapperConfig config = DynamoDBMapperConfig.builder() .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.CLOBBER).build(); mapper.save(item, config);

버전 관리를 활성화하면 클라이언트 측 항목 버전과 서버 측 항목 버전이 일치해야 합니다. 하지만 SaveBehavior.CLOBBER 옵션을 사용하면 버전이 일치하지 않아도 괜찮습니다. 버전 관리에 대한 자세한 내용은 버전 번호를 이용한 낙관적 잠금 섹션을 참조하십시오.

로드

테이블에서 항목을 가져옵니다. 검색할 항목의 기본 키를 제공해야 합니다. DynamoDBMapperConfig 객체를 사용하여 옵션으로 구성 파라미터를 입력할 수도 있습니다. 예를 들어 아래 Java 문과 같이 이 메서드를 실행하여 최신 항목 값만 가져오려면 옵션으로 strongly consistent read를 요청하면 됩니다.

DynamoDBMapperConfig config = DynamoDBMapperConfig.builder() .withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT).build(); CatalogItem item = mapper.load(CatalogItem.class, item.getId(), config);

기본적으로 DynamoDB는 최종적으로 일관된 값을 갖는 항목을 반환하기 때문입니다. DynamoDB의 최종 일관성 모델에 대한 자세한 내용은 읽기 정합성 단원을 참조하세요.

delete

항목을 테이블에서 삭제합니다. 이때는 매핑된 클래스의 객체 인스턴스를 전달해야 합니다.

버전 관리를 활성화하면 클라이언트 측 항목 버전과 서버 측 항목 버전이 일치해야 합니다. 하지만 SaveBehavior.CLOBBER 옵션을 사용하면 버전이 일치하지 않아도 괜찮습니다. 버전 관리에 대한 자세한 내용은 버전 번호를 이용한 낙관적 잠금 섹션을 참조하십시오.

쿼리

테이블 또는 보조 인덱스를 쿼리합니다. 테이블에 복합 기본 키(파티션 키 및 정렬 키)가 있는 경우에만 테이블 또는 인덱스를 쿼리할 수 있습니다. 이 메서드를 실행하려면 파티션 키 값을 비롯해 정렬 키에 적용되는 쿼리 필터를 입력해야 합니다. 필터 표현식에는 조건과 값이 추가됩니다.

포럼 스레드 회신이 저장되는 Reply 테이블이 있는 경우 스레드 제목마다 회신 수가 0개 또는 그 이상이 될 수 있습니다. Reply 테이블의 기본 키는 IdReplyDateTime 필드로 구성됩니다. 여기에서 Id는 파티션 키이고, ReplyDateTime은 기본 키의 정렬 키입니다.

Reply ( Id, ReplyDateTime, ... )

Reply 클래스와 DynamoDB의 해당 Reply 테이블 간 매핑을 생성한 경우 다음 Java 코드는 DynamoDBMapper를 사용하여 특정 스레드 제목에 대한 지난 2주 간 모든 회신을 찾습니다.

String forumName = "&DDB;"; String forumSubject = "&DDB; Thread 1"; String partitionKey = forumName + "#" + forumSubject; long twoWeeksAgoMilli = (new Date()).getTime() - (14L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS(partitionKey)); eav.put(":v2",new AttributeValue().withS(twoWeeksAgoStr.toString())); DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>() .withKeyConditionExpression("Id = :v1 and ReplyDateTime > :v2") .withExpressionAttributeValues(eav); List<Reply> latestReplies = mapper.query(Reply.class, queryExpression);

쿼리 결과 Reply 객체 컬렉션이 반환됩니다.

기본적으로 query 메서드는 "지연 로딩된(lazy-loaded)" 컬렉션을 반환합니다. 즉, 처음에는 결과 페이지를 하나만 반환하고, 필요에 따라 서비스를 호출하여 다음 페이지를 반환합니다. 일치하는 항목을 모두 가져오려면 latestReplies 컬렉션을 반복합니다.

컬렉션에서 size() 메서드를 호출하면 정확한 개수를 제공하기 위해 모든 결과가 로드됩니다. 이로 인해 프로비저닝된 처리량이 많이 사용될 수 있으며, 매우 큰 테이블에서는 JVM의 모든 메모리가 소모될 수도 있습니다.

인덱스를 쿼리하려면 먼저 인덱스를 매퍼 클래스로 모델링해야 합니다. Reply테이블에 -Message-Index라는 글로벌 보조 인덱스가 있다고 가정해 보겠습니다. PostedBy 이 인덱스의 파티션 키는 PostedBy이고, 정렬 키는 Message입니다. 이 인덱스에서 항목의 클래스 정의는 다음과 같을 것입니다.

@DynamoDBTable(tableName="Reply") public class PostedByMessage { private String postedBy; private String message; @DynamoDBIndexHashKey(globalSecondaryIndexName = "PostedBy-Message-Index", attributeName = "PostedBy") public String getPostedBy() { return postedBy; } public void setPostedBy(String postedBy) { this.postedBy = postedBy; } @DynamoDBIndexRangeKey(globalSecondaryIndexName = "PostedBy-Message-Index", attributeName = "Message") public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } // Additional properties go here. }

@DynamoDBTable 주석은 이 인덱스가 Reply 테이블과 연결되어 있음을 나타냅니다. @DynamoDBIndexHashKey주석은 인덱스의 파티션 키 (PostedBy) 를 나타내고 인덱스의 정렬 키 (메시지) 를 @DynamoDBIndexRangeKey 나타냅니다.

이제 DynamoDBMapper를 사용하여 특정 사용자가 게시한 메시지 하위 집합을 검색하는 인덱스 쿼리를 실행할 수 있습니다. 테이블과 인덱스에 충돌하는 매핑이 없고 매핑이 이미 매퍼에서 만들어진 경우에는 인덱스 이름을 지정할 필요가 없습니다. 매퍼는 프라이머리 키와 정렬 키를 기반으로 추론합니다. 다음 코드에서는 글로벌 보조 인덱스를 쿼리합니다. 글로벌 보조 인덱스는 최종적 일관된 읽기는 지원하지만 강력히 일관된 읽기는 지원하지 않으므로 withConsistentRead(false)를 지정해야 합니다.

HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("User A")); eav.put(":v2", new AttributeValue().withS("DynamoDB")); DynamoDBQueryExpression<PostedByMessage> queryExpression = new DynamoDBQueryExpression<PostedByMessage>() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false) .withKeyConditionExpression("PostedBy = :v1 and begins_with(Message, :v2)") .withExpressionAttributeValues(eav); List<PostedByMessage> iList = mapper.query(PostedByMessage.class, queryExpression);

쿼리 결과 PostedByMessage 객체 컬렉션이 반환됩니다.

queryPage

테이블 또는 보조 인덱스를 쿼리하고 일치하는 결과를 단일 페이지로 반환합니다. query 메서드에서 그랬듯이 이번에도 파티션 키 값을 비롯해 정렬 키 속성에 적용되는 쿼리 필터를 지정해야 합니다. 그러나 queryPage는 첫 번째 데이터 "페이지"만 반환합니다. 다시 말해서 1M를 넘지 않는 범위에서 데이터를 반환합니다.

스캔

전체 테이블 또는 보조 인덱스를 스캔합니다. FilterExpression를 지정하여 결과 집합을 필터링할 수도 있습니다(선택 사항).

포럼 스레드 회신이 저장되는 Reply 테이블이 있는 경우 스레드 제목마다 회신 수가 0개 또는 그 이상이 될 수 있습니다. Reply 테이블의 기본 키는 IdReplyDateTime 필드로 구성됩니다. 여기에서 Id는 파티션 키이고, ReplyDateTime은 기본 키의 정렬 키입니다.

Reply ( Id, ReplyDateTime, ... )

Java 클래스를 Reply 테이블로 매핑한 경우 DynamoDBMapper를 사용하여 테이블을 스캔할 수 있습니다. 예를 들어, 다음 Java 코드에서는 전체 Reply 테이블을 스캔하여 특정 연도의 회신만 반환합니다.

HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":v1", new AttributeValue().withS("2015")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("begins_with(ReplyDateTime,:v1)") .withExpressionAttributeValues(eav); List<Reply> replies = mapper.scan(Reply.class, scanExpression);

기본적으로 scan 메서드는 "지연 로딩된(lazy-loaded)" 컬렉션을 반환합니다. 즉, 처음에는 결과 페이지를 하나만 반환하고, 필요에 따라 서비스를 호출하여 다음 페이지를 반환합니다. 일치하는 항목을 모두 가져오려면 replies 컬렉션을 반복합니다.

컬렉션에서 size() 메서드를 호출하면 정확한 개수를 제공하기 위해 모든 결과가 로드됩니다. 이로 인해 프로비저닝된 처리량이 많이 사용될 수 있으며, 매우 큰 테이블에서는 JVM의 모든 메모리가 소모될 수도 있습니다.

인덱스를 스캔하려면 먼저 인덱스를 매퍼 클래스로 모델링해야 합니다. Reply 테이블에 PostedBy-Message-Index라는 글로벌 보조 인덱스가 있다고 가정합니다. 이 인덱스의 파티션 키는 PostedBy이고, 정렬 키는 Message입니다. 이 인덱스에 대한 매퍼 클래스는 쿼리 단원에 나와 있습니다. 이 클래스는 @DynamoDBIndexHashKey@DynamoDBIndexRangeKey 주석을 사용하여 인덱스 파티션 키 및 정렬 키를 지정합니다.

다음 코드 예제에서는 PostedBy-Message-Index를 스캔합니다. 스캔 필터를 사용하지 않으므로 인덱스의 모든 항목이 반환됩니다.

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withIndexName("PostedBy-Message-Index") .withConsistentRead(false); List<PostedByMessage> iList = mapper.scan(PostedByMessage.class, scanExpression); Iterator<PostedByMessage> indexItems = iList.iterator();

scanPage

테이블 또는 보조 인덱스를 스캔하고 일치하는 결과를 단일 페이지로 반환합니다. scan 메서드와 마찬가지로 FilterExpression을 지정하여 결과 집합을 필터링할 수도 있습니다(선택 사항). 그러나 scanPage는 첫 번째 데이터 ‘페이지’만 반환합니다. 다시 말해서 1MB를 넘지 않는 범위에서 데이터를 반환합니다.

parallelScan

전체 테이블 또는 보조 인덱스를 병렬 방식으로 스캔합니다. 즉, 결과를 필터링할 스캔 표현식과 함께 테이블의 논리 세그먼트를 다수 지정합니다. parallelScan은 스캔 작업을 각 논리 세그먼트마다 하나씩 여러 작업자로 분할합니다. 그러면 작업자가 데이터를 병렬 방식으로 처리하여 결과를 반환합니다.

다음 Java 코드 예제에서는 Product 테이블에 대한 병렬 스캔을 수행합니다.

int numberOfThreads = 4; Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>(); eav.put(":n", new AttributeValue().withN("100")); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withFilterExpression("Price <= :n") .withExpressionAttributeValues(eav); List<Product> scanResult = mapper.parallelScan(Product.class, scanExpression, numberOfThreads);

parallelScan의 사용법을 나타낸 Java 코드 예제는 DynamoDBMapper 쿼리 및 스캔 작업 단원을 참조하세요.

batchSave

AmazonDynamoDB.batchWriteItem 메서드를 1회 이상 호출하여 객체를 하나 이상의 테이블에 저장합니다. 이 메서드는 트랜잭션을 보장하지는 않습니다.

다음 Java 코드에서는 두 항목(책)을 ProductCatalog 테이블에 저장합니다.

Book book1 = new Book(); book1.setId(901); book1.setProductCategory("Book"); book1.setTitle("Book 901 Title"); Book book2 = new Book(); book2.setId(902); book2.setProductCategory("Book"); book2.setTitle("Book 902 Title"); mapper.batchSave(Arrays.asList(book1, book2));

batchLoad

기본 키를 사용하여 다수의 항목을 하나 이상의 테이블에서 가져옵니다.

다음 Java 코드에서는 두 개의 서로 다른 테이블에서 두 개의 항목을 검색합니다.

ArrayList<Object> itemsToGet = new ArrayList<Object>(); ForumItem forumItem = new ForumItem(); forumItem.setForumName("Amazon DynamoDB"); itemsToGet.add(forumItem); ThreadItem threadItem = new ThreadItem(); threadItem.setForumName("Amazon DynamoDB"); threadItem.setSubject("Amazon DynamoDB thread 1 message text"); itemsToGet.add(threadItem); Map<String, List<Object>> items = mapper.batchLoad(itemsToGet);

batchDelete

AmazonDynamoDB.batchWriteItem 메서드를 1회 이상 호출하여 객체를 하나 이상의 테이블에서 삭제합니다. 이 메서드는 트랜잭션을 보장하지는 않습니다.

다음은 Java 코드에서는 ProductCatalog 테이블에서 두 항목(책)을 삭제합니다.

Book book1 = mapper.load(Book.class, 901); Book book2 = mapper.load(Book.class, 902); mapper.batchDelete(Arrays.asList(book1, book2));

batchWrite

AmazonDynamoDB.batchWriteItem 메서드를 1회 이상 호출하여 객체를 하나 이상의 테이블에 저장하거나 삭제합니다. 이 메서드는 트랜잭션을 보장하거나 버전 관리를 지원하지 않습니다(조건부 업로드 또는 삭제).

다음 Java 코드에서는 새 항목을 Forum 테이블에 쓰고, 새 항목을 Thread 테이블에 쓰고, ProductCatalog 테이블에서 항목을 삭제합니다.

// Create a Forum item to save Forum forumItem = new Forum(); forumItem.setName("Test BatchWrite Forum"); // Create a Thread item to save Thread threadItem = new Thread(); threadItem.setForumName("AmazonDynamoDB"); threadItem.setSubject("My sample question"); // Load a ProductCatalog item to delete Book book3 = mapper.load(Book.class, 903); List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem); List<Book> objectsToDelete = Arrays.asList(book3); mapper.batchWrite(objectsToWrite, objectsToDelete);

transactionWrite

AmazonDynamoDB.transactWriteItems 메서드를 1회 호출하여 객체를 하나 이상의 테이블에 저장하거나 삭제합니다.

트랜잭션별 예외 목록은 오류를 참조하십시오. TransactWriteItems

DynamoDB 트랜잭션과 제공된 원자성, 일관성, 격리성 및 지속성(ACID) 보장에 대한 자세한 내용은 Amazon DynamoDB Transactions를 참조하세요.

참고

이 메서드는 다음을 지원하지 않습니다.

다음 Java 코드에서는 트랜잭션 형태로 각 ForumThread 테이블에 새 항목을 씁니다.

Thread s3ForumThread = new Thread(); s3ForumThread.setForumName("S3 Forum"); s3ForumThread.setSubject("Sample Subject 1"); s3ForumThread.setMessage("Sample Question 1"); Forum s3Forum = new Forum(); s3Forum.setName("S3 Forum"); s3Forum.setCategory("Amazon Web Services"); s3Forum.setThreads(1); TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest(); transactionWriteRequest.addPut(s3Forum); transactionWriteRequest.addPut(s3ForumThread); mapper.transactionWrite(transactionWriteRequest);

transactionLoad

AmazonDynamoDB.transactGetItems 메서드를 1회 호출하여 객체를 하나 이상의 테이블에서 로드합니다.

트랜잭션별 예외 목록은 오류를 참조하십시오. TransactGetItems

DynamoDB 트랜잭션과 제공된 원자성, 일관성, 격리성 및 지속성(ACID) 보장에 대한 자세한 내용은 Amazon DynamoDB Transactions를 참조하세요.

다음 Java 코드에서는 트랜잭션 형태로 각 ForumThread 테이블에서 한 개의 항목을 로드합니다.

Forum dynamodbForum = new Forum(); dynamodbForum.setName("DynamoDB Forum"); Thread dynamodbForumThread = new Thread(); dynamodbForumThread.setForumName("DynamoDB Forum"); TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest(); transactionLoadRequest.addLoad(dynamodbForum); transactionLoadRequest.addLoad(dynamodbForumThread); mapper.transactionLoad(transactionLoadRequest);

count

지정한 스캔 표현식을 평가하여 일치하는 항목 수를 반환합니다. 항목 데이터를 따로 반환하지는 않습니다.

generateCreateTable요청

DynamoDB 테이블을 나타내는 POJO 클래스를 구문 분석한 다음 해당 테이블의 CreateTableRequest를 반환합니다.

Amazon S3 객체에 대한 링크를 생성합니다. 이때 버킷 객체의 고유 식별자로서 버킷 이름과 키 이름을 지정해야 합니다.

createS3Link를 사용하려면 접근자(getter/setter) 메서드를 정의해야 합니다. 다음 코드 예제에서는 새 속성 및 getter/setter 메서드를 CatalogItem 클래스에 추가하여 이를 설명합니다.

@DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { ... public S3Link productImage; .... @DynamoDBAttribute(attributeName = "ProductImage") public S3Link getProductImage() { return productImage; } public void setProductImage(S3Link productImage) { this.productImage = productImage; } ... }

다음 Java 코드에서는 Product 테이블에 쓸 새 항목을 정의합니다. 코드를 보면 항목에 제품 이미지 링크가 추가되어 있습니다. 이 이미지 데이터는 Amazon S3에 업로드됩니다.

CatalogItem item = new CatalogItem(); item.setId(150); item.setTitle("Book 150 Title"); String myS3Bucket = "myS3bucket"; String myS3Key = "productImages/book_150_cover.jpg"; item.setProductImage(mapper.createS3Link(myS3Bucket, myS3Key)); item.getProductImage().uploadFrom(new File("/file/path/book_150_cover.jpg")); mapper.save(item);

S3Link 클래스는 Amazon S3의 객체를 조작할 수 있는 여러 가지 다른 메서드를 제공합니다. 자세한 내용은 S3Link Javadocs를 참조하세요.

GetS3 ClientCache

Amazon S3에 액세스할 수 있는 기본 S3ClientCache를 반환합니다. S3ClientCacheAmazonS3Client 객체를 위한 스마트 맵입니다. 클라이언트가 여러 개 있는 경우 클라이언트를 AWS 지역별로 정리하는 데 도움이 되며 필요에 따라 새 Amazon S3 클라이언트를 생성할 수 있습니다. S3ClientCache