Azure Tables SDK for Java
Build table storage applications using the Azure Tables SDK for Java. Works with both Azure Table Storage and Cosmos DB Table API.
Installation
<dependency> <groupId>com.azure</groupId> <artifactId>azure-data-tables</artifactId> <version>12.6.0-beta.1</version> </dependency>
Client Creation
With Connection String
import com.azure.data.tables.TableServiceClient; import com.azure.data.tables.TableServiceClientBuilder; import com.azure.data.tables.TableClient;
TableServiceClient serviceClient = new TableServiceClientBuilder() .connectionString("<your-connection-string>") .buildClient();
With Shared Key
import com.azure.core.credential.AzureNamedKeyCredential;
AzureNamedKeyCredential credential = new AzureNamedKeyCredential( "<account-name>", "<account-key>");
TableServiceClient serviceClient = new TableServiceClientBuilder() .endpoint("<your-table-account-url>") .credential(credential) .buildClient();
With SAS Token
TableServiceClient serviceClient = new TableServiceClientBuilder() .endpoint("<your-table-account-url>") .sasToken("<sas-token>") .buildClient();
With DefaultAzureCredential (Storage only)
import com.azure.identity.DefaultAzureCredentialBuilder;
TableServiceClient serviceClient = new TableServiceClientBuilder() .endpoint("<your-table-account-url>") .credential(new DefaultAzureCredentialBuilder().build()) .buildClient();
Key Concepts
-
TableServiceClient: Manage tables (create, list, delete)
-
TableClient: Manage entities within a table (CRUD)
-
Partition Key: Groups entities for efficient queries
-
Row Key: Unique identifier within a partition
-
Entity: A row with up to 252 properties (1MB Storage, 2MB Cosmos)
Core Patterns
Create Table
// Create table (throws if exists) TableClient tableClient = serviceClient.createTable("mytable");
// Create if not exists (no exception) TableClient tableClient = serviceClient.createTableIfNotExists("mytable");
Get Table Client
// From service client TableClient tableClient = serviceClient.getTableClient("mytable");
// Direct construction TableClient tableClient = new TableClientBuilder() .connectionString("<connection-string>") .tableName("mytable") .buildClient();
Create Entity
import com.azure.data.tables.models.TableEntity;
TableEntity entity = new TableEntity("partitionKey", "rowKey") .addProperty("Name", "Product A") .addProperty("Price", 29.99) .addProperty("Quantity", 100) .addProperty("IsAvailable", true);
tableClient.createEntity(entity);
Get Entity
TableEntity entity = tableClient.getEntity("partitionKey", "rowKey");
String name = (String) entity.getProperty("Name"); Double price = (Double) entity.getProperty("Price"); System.out.printf("Product: %s, Price: %.2f%n", name, price);
Update Entity
import com.azure.data.tables.models.TableEntityUpdateMode;
// Merge (update only specified properties) TableEntity updateEntity = new TableEntity("partitionKey", "rowKey") .addProperty("Price", 24.99); tableClient.updateEntity(updateEntity, TableEntityUpdateMode.MERGE);
// Replace (replace entire entity) TableEntity replaceEntity = new TableEntity("partitionKey", "rowKey") .addProperty("Name", "Product A Updated") .addProperty("Price", 24.99) .addProperty("Quantity", 150); tableClient.updateEntity(replaceEntity, TableEntityUpdateMode.REPLACE);
Upsert Entity
// Insert or update (merge mode) tableClient.upsertEntity(entity, TableEntityUpdateMode.MERGE);
// Insert or replace tableClient.upsertEntity(entity, TableEntityUpdateMode.REPLACE);
Delete Entity
tableClient.deleteEntity("partitionKey", "rowKey");
List Entities
import com.azure.data.tables.models.ListEntitiesOptions;
// List all entities for (TableEntity entity : tableClient.listEntities()) { System.out.printf("%s - %s%n", entity.getPartitionKey(), entity.getRowKey()); }
// With filtering and selection ListEntitiesOptions options = new ListEntitiesOptions() .setFilter("PartitionKey eq 'sales'") .setSelect("Name", "Price");
for (TableEntity entity : tableClient.listEntities(options, null, null)) { System.out.printf("%s: %.2f%n", entity.getProperty("Name"), entity.getProperty("Price")); }
Query with OData Filter
// Filter by partition key ListEntitiesOptions options = new ListEntitiesOptions() .setFilter("PartitionKey eq 'electronics'");
// Filter with multiple conditions options.setFilter("PartitionKey eq 'electronics' and Price gt 100");
// Filter with comparison operators options.setFilter("Quantity ge 10 and Quantity le 100");
// Top N results options.setTop(10);
for (TableEntity entity : tableClient.listEntities(options, null, null)) { System.out.println(entity.getRowKey()); }
Batch Operations (Transactions)
import com.azure.data.tables.models.TableTransactionAction; import com.azure.data.tables.models.TableTransactionActionType; import java.util.Arrays;
// All entities must have same partition key List<TableTransactionAction> actions = Arrays.asList( new TableTransactionAction( TableTransactionActionType.CREATE, new TableEntity("batch", "row1").addProperty("Name", "Item 1")), new TableTransactionAction( TableTransactionActionType.CREATE, new TableEntity("batch", "row2").addProperty("Name", "Item 2")), new TableTransactionAction( TableTransactionActionType.UPSERT_MERGE, new TableEntity("batch", "row3").addProperty("Name", "Item 3")) );
tableClient.submitTransaction(actions);
List Tables
import com.azure.data.tables.models.TableItem; import com.azure.data.tables.models.ListTablesOptions;
// List all tables for (TableItem table : serviceClient.listTables()) { System.out.println(table.getName()); }
// Filter tables ListTablesOptions options = new ListTablesOptions() .setFilter("TableName eq 'mytable'");
for (TableItem table : serviceClient.listTables(options, null, null)) { System.out.println(table.getName()); }
Delete Table
serviceClient.deleteTable("mytable");
Typed Entities
public class Product implements TableEntity { private String partitionKey; private String rowKey; private OffsetDateTime timestamp; private String eTag; private String name; private double price;
// Getters and setters for all fields
@Override
public String getPartitionKey() { return partitionKey; }
@Override
public void setPartitionKey(String partitionKey) { this.partitionKey = partitionKey; }
@Override
public String getRowKey() { return rowKey; }
@Override
public void setRowKey(String rowKey) { this.rowKey = rowKey; }
// ... other getters/setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}
// Usage Product product = new Product(); product.setPartitionKey("electronics"); product.setRowKey("laptop-001"); product.setName("Laptop"); product.setPrice(999.99);
tableClient.createEntity(product);
Error Handling
import com.azure.data.tables.models.TableServiceException;
try { tableClient.createEntity(entity); } catch (TableServiceException e) { System.out.println("Status: " + e.getResponse().getStatusCode()); System.out.println("Error: " + e.getMessage()); // 409 = Conflict (entity exists) // 404 = Not Found }
Environment Variables
Storage Account
AZURE_TABLES_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=... AZURE_TABLES_ENDPOINT=https://<account>.table.core.windows.net
Cosmos DB Table API
COSMOS_TABLE_ENDPOINT=https://<account>.table.cosmosdb.azure.com
Best Practices
-
Partition Key Design: Choose keys that distribute load evenly
-
Batch Operations: Use transactions for atomic multi-entity updates
-
Query Optimization: Always filter by PartitionKey when possible
-
Select Projection: Only select needed properties for performance
-
Entity Size: Keep entities under 1MB (Storage) or 2MB (Cosmos)
Trigger Phrases
-
"Azure Tables Java"
-
"table storage SDK"
-
"Cosmos DB Table API"
-
"NoSQL key-value storage"
-
"partition key row key"
-
"table entity CRUD"