All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTableMapper Maven / Gradle / Ivy

Go to download

The AWS Java SDK for Amazon DynamoDB module holds the client classes that are used for communicating with Amazon DynamoDB Service

There is a newer version: 1.9.11
Show newest version
/*
 * Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and
 * limitations under the License.
 */
package com.amazonaws.services.dynamodbv2.datamodeling;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDeleteExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBSaveExpression;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ResourceInUseException;
import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException;
import com.amazonaws.services.dynamodbv2.model.TableDescription;
import com.amazonaws.services.s3.model.Region;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A wrapper for {@code DynamoDBMapper} which operates only on a specified
 * class/table.  All calls are forwarded to the underlying
 * {@code DynamoDBMapper} which was used to create this table mapper.
 *
 * A minimal example using get annotations,
 * 
 * @DynamoDBTable(tableName="TestTable")
 * public class TestClass {
 *     private Long key;
 *     private String rangeKey;
 *     private Double amount;
 *     private Long version;
 *
 *     @DynamoDBHashKey
 *     public Long getKey() { return key; }
 *     public void setKey(Long key) { this.key = key; }
 *
 *     @DynamoDBRangeKey
 *     public String getRangeKey() { return rangeKey; }
 *     public void setRangeKey(String rangeKey) { this.rangeKey = rangeKey; }
 *
 *     @DynamoDBAttribute(attributeName="amount")
 *     public Double getAmount() { return amount; }
 *     public void setAmount(Double amount) { this.amount = amount; }
 *
 *     @DynamoDBVersionAttribute
 *     public Long getVersion() { return version; }
 *     public void setVersion(Long version) { this.version = version; }
 * }
 * 
* * Initialize the DynamoDB mapper, *
 * AmazonDynamoDB dbClient = new AmazonDynamoDBClient();
 * DynamoDBMapper dbMapper = new DynamoDBMapper(dbClient);
 * 
* * Then, create a new table mapper with hash and range key, *
 * DynamoDBTableMapper<TestClass,Long,String> mapper = dbMapper.newTableMapper(TestClass.class);
 * 
* * Or, if the table does not have a range key, *
 * DynamoDBTableMapper<TestClass,Long,?> mapper = dbMapper.newTableMapper(TestClass.class);
 * 
* * If you don't have your DynamoDB table set up yet, you can use, *
 * mapper.createTableIfNotExists(new ProvisionedThroughput(25L, 25L));
 * 
* * Save instances of annotated classes and retrieve them, *
 * TestClass object = new TestClass();
 * object.setKey(1234L);
 * object.setRangeKey("ABCD");
 * object.setAmount(101D);
 *
 * try {
 *     mapper.saveIfNotExists(object);
 * } catch (ConditionalCheckFailedException e) {
 *     // handle already existing
 * }
 * 
* * Execute a query operation, *
 * int limit = 10;
 * List<TestClass> objects = new ArrayList<TestClass>(limit);
 *
 * DynamoDBQueryExpression<TestClass> query = mapper.queryExpressionOf(1234L)
 *     .withRangeKeyCondition(mapper..rangeKey().name(), mapper.rangeKey().ge("ABAA"))
 *     .withQueryFilterEntry("amount", mapper.field("amount").gt(100D))
 *     .withConsistentReads(true);
 *
 * QueryResultPage<TestClass> results = new QueryResultPage<TestClass>();
 *
 * do {
 *     if (results.getLastEvaluatedKey() != null) {
 *         query.setExclusiveStartKey(results.getLastEvaluatedKey());
 *     }
 *     query.setLimit(limit - objects.size());
 *     results = mapper.query(query);
 *     for (TestClass object : results.getResults()) {
 *         objects.add(object);
 *     }
 * } while (results.getLastEvaluatedKey() != null && objects.size() < limit)
 * 
* * @param The object type which this mapper operates. * @param The hash key value type. * @param The range key value type; use ? if no range key. * * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper * @see com.amazonaws.services.dynamodbv2.AmazonDynamoDB */ public final class DynamoDBTableMapper { private static final Log LOG = LogFactory.getLog(DynamoDBTableMapper.class); private final DynamoDBMapperTableModel model; private final DynamoDBMapperFieldModel hk; private final DynamoDBMapperFieldModel rk; private final DynamoDBMapper mapper; private final AmazonDynamoDB db; /** * Constructs a new table mapper for the given class. * @param model The field model factory. * @param mapper The DynamoDB mapper. * @param db The service object to use for all service calls. */ protected DynamoDBTableMapper(final DynamoDBMapperTableModel model, final DynamoDBMapper mapper, final AmazonDynamoDB db) { this.rk = model.rangeKeyIfExists(); this.hk = model.hashKey(); this.model = model; this.mapper = mapper; this.db = db; } /** * Gets the field model for a given attribute. * @param The field model's value type. * @param attributeName The attribute name. * @return The field model. */ public DynamoDBMapperFieldModel field(final String attributeName) { return this.model.field(attributeName); } /** * Gets the hash key field model for the specified type. * @param The hash key type. * @return The hash key field model. * @throws DynamoDBMappingException If the hash key is not present. */ public DynamoDBMapperFieldModel hashKey() { return this.model.hashKey(); } /** * Gets the range key field model for the specified type. * @param The range key type. * @return The range key field model. * @throws DynamoDBMappingException If the range key is not present. */ public DynamoDBMapperFieldModel rangeKey() { return this.model.rangeKey(); } /** * Retrieves multiple items from the table using their primary keys. * @param itemsToGet The items to get. * @return The list of objects. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#batchLoad */ public final List batchLoad(final Iterable itemsToGet) { final Map> results = mapper.batchLoad(itemsToGet); return results.isEmpty() ? Collections.emptyList() : (List)results.get(model.tableName()); } /** * Saves the objects given using one or more calls to the batchWriteItem API. * @param objectsToSave The objects to save. * @return The list of failed batches. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#batchSave */ public final List batchSave(final Iterable objectsToSave) { return mapper.batchWrite(objectsToSave, (Iterable)Collections.emptyList()); } /** * Deletes the objects given using one or more calls to the batchWtiteItem API. * @param objectsToDelete The objects to delete. * @return The list of failed batches. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#batchDelete */ public final List batchDelete(final Iterable objectsToDelete) { return mapper.batchWrite((Iterable)Collections.emptyList(), objectsToDelete); } /** * Saves and deletes the objects given using one or more calls to the * batchWriteItem API. * @param objectsToWrite The objects to write. * @param objectsToDelete The objects to delete. * @return The list of failed batches. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#batchWrite */ public final List batchWrite(final Iterable objectsToWrite, final Iterable objectsToDelete) { return mapper.batchWrite(objectsToWrite, objectsToDelete); } /** * Loads an object with the hash key given. * @param hashKey The hash key value. * @return The object. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#load */ public final T load(final H hashKey) { return mapper.load(model.targetType(), hashKey); } /** * Loads an object with the hash and range key. * @param hashKey The hash key value. * @param rangeKey The range key value. * @return The object. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#load */ public final T load(final H hashKey, final R rangeKey) { return mapper.load(model.targetType(), hashKey, rangeKey); } /** * Saves the object given into DynamoDB. * @param object The object to save. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#save */ public final void save(final T object) { mapper.save(object); } /** * Saves the object given into DynamoDB using the specified saveExpression. * @param object The object to save. * @param saveExpression The save expression. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#save */ public final void save(final T object, final DynamoDBSaveExpression saveExpression) { mapper.save(object, saveExpression); } /** * Saves the object given into DynamoDB with the condition that the hash * and if applicable, the range key, does not already exist. * @param object The object to create. * @throws ConditionalCheckFailedException If the object exists. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#save * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBSaveExpression * @see com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue */ public final void saveIfNotExists(final T object) throws ConditionalCheckFailedException { final DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); saveExpression.withExpectedEntry(hk.name(), hk.expectedNotExists()); if (rk != null) { saveExpression.withExpectedEntry(rk.name(), rk.expectedNotExists()); } mapper.save(object, saveExpression); } /** * Saves the object given into DynamoDB with the condition that the hash * and, if applicable, the range key, already exist. * @param object The object to update. * @throws ConditionalCheckFailedException If the object does not exist. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#save * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBSaveExpression * @see com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue */ public final void saveIfExists(final T object) throws ConditionalCheckFailedException { final DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); saveExpression.withExpectedEntry(hk.name(), hk.expectedExists(hk.get(object))); if (rk != null) { saveExpression.withExpectedEntry(rk.name(), rk.expectedExists(rk.get(object))); } mapper.save(object, saveExpression); } /** * Deletes the given object from its DynamoDB table. * @param object The object to delete. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#delete */ public final void delete(final T object) { mapper.delete(object); } /** * Deletes the given object from its DynamoDB table using the specified * deleteExpression. * @param object The object to delete. * @param deleteExpression The delete expression. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#delete */ public final void delete(final T object, final DynamoDBDeleteExpression deleteExpression) { mapper.delete(object, deleteExpression); } /** * Deletes the given object from its DynamoDB table with the condition that * the hash and, if applicable, the range key, already exist. * @param object The object to delete. * @throws ConditionalCheckFailedException If the object does not exist. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#delete * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDeleteExpression * @see com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue */ public final void deleteIfExists(final T object) throws ConditionalCheckFailedException { final DynamoDBDeleteExpression deleteExpression = new DynamoDBDeleteExpression(); deleteExpression.withExpectedEntry(hk.name(), hk.expectedExists(hk.get(object))); if (rk != null) { deleteExpression.withExpectedEntry(rk.name(), rk.expectedExists(rk.get(object))); } mapper.delete(object, deleteExpression); } /** * Evaluates the specified query expression and returns the count of matching * items, without returning any of the actual item data * @param queryExpression The query expression. * @return The count. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#count */ public final int count(final DynamoDBQueryExpression queryExpression) { return mapper.count(model.targetType(), queryExpression); } /** * Queries an Amazon DynamoDB table and returns the matching results as an * unmodifiable list of instantiated objects. * @param queryExpression The query expression. * @return The query results. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#query */ public final QueryResultPage query(final DynamoDBQueryExpression queryExpression) { return mapper.queryPage(model.targetType(), queryExpression); } /** * Queries an Amazon DynamoDB table and returns a single page of matching * results. * @param queryExpression The query expression. * @return The query results. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#query */ public final QueryResultPage queryPage(final DynamoDBQueryExpression queryExpression) { return mapper.queryPage(model.targetType(), queryExpression); } /** * Evaluates the specified scan expression and returns the count of matching * items, without returning any of the actual item data. * @param scanExpression The scan expression. * @return The count. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#count */ public final int count(final DynamoDBScanExpression scanExpression) { return mapper.count(model.targetType(), scanExpression); } /** * Scans through an Amazon DynamoDB table and returns the matching results * as an unmodifiable list of instantiated objects. * @param scanExpression The scan expression. * @return The scan results. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#scan */ public final PaginatedScanList scan(final DynamoDBScanExpression scanExpression) { return mapper.scan(model.targetType(), scanExpression); } /** * Scans through an Amazon DynamoDB table and returns a single page of * matching results. * @param scanExpression The scan expression. * @return The scan results. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#scanPage */ public final ScanResultPage scanPage(final DynamoDBScanExpression scanExpression) { return mapper.scanPage(model.targetType(), scanExpression); } /** * Scans through an Amazon DynamoDB table on logically partitioned segments * in parallel and returns the matching results in one unmodifiable list of * instantiated objects. * @param scanExpression The scan expression. * @param totalSegments The total segments. * @return The scan results. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#parallelScan */ public final PaginatedParallelScanList parallelScan(final DynamoDBScanExpression scanExpression, int totalSegments) { return mapper.parallelScan(model.targetType(), scanExpression, totalSegments); } /** * Creates an S3Link with the specified region, bucket name and key. * @param s3region The S3 region. * @param bucketName The bucket name. * @param key The key. * @return The created S3Link. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#createS3Link */ public final S3Link createS3Link(final Region s3region, final String bucketName, final String key) { return mapper.createS3Link(s3region, bucketName, key); } /** * Creates an S3Link with the specified bucket name and key using the * default S3 region. * @param bucketName The bucket name. * @param key The key. * @return The created S3Link. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#createS3Link */ public final S3Link createS3Link(final String bucketName, final String key) { return mapper.createS3Link(bucketName, key); } /** * Returns the underlying S3ClientCache for accessing S3. * @return The underlying S3ClientCache. * @see com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper#getS3ClientCache */ public final S3ClientCache getS3ClientCache() { return mapper.getS3ClientCache(); } /** * Returns information about the table, including the current status of the * table, when it was created, the primary key schema, and any indexes on * the table. * @return The describe table results. * @see com.amazonaws.services.dynamodbv2.AmazonDynamoDB#describeTable */ public final TableDescription describeTable() { return db.describeTable(model.tableName()).getTable(); } /** * Creates the table and ignores the {@code ResourceInUseException} if it * ialready exists. * @param throughput The provisioned throughput. * @return True if created, or false if the table already existed. * @see com.amazonaws.services.dynamodbv2.AmazonDynamoDB#createTable * @see com.amazonaws.services.dynamodbv2.model.CreateTableRequest */ public final boolean createTableIfNotExists(final ProvisionedThroughput throughput) { try { db.createTable(mapper.generateCreateTableRequest(model.targetType()).withProvisionedThroughput(throughput)); } catch (final ResourceInUseException e) { if (LOG.isTraceEnabled()) { LOG.trace("Table " + model.tableName() + " already exists, no need to create", e); } return false; } return true; } /** * Deletes the table and ignores the {@code ResourceNotFoundException} if * it does not already exist. * @return True if the table was deleted, or false if the table did not exist. * @see com.amazonaws.services.dynamodbv2.AmazonDynamoDB#deleteTable * @see com.amazonaws.services.dynamodbv2.model.DeleteTableRequest */ public final boolean deleteTableIfExists() { try { db.deleteTable(mapper.generateDeleteTableRequest(model.targetType())); } catch (final ResourceNotFoundException e) { if (LOG.isTraceEnabled()) { LOG.trace("Table " + model.tableName() + " does not exist, no need to delete", e); } return false; } return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy