如何使用適用於 Java 的 Azure 資料表用戶端程式庫

適用於: 桌子

提示

本文中的內容適用於 Azure 資料表儲存體和 Azure Cosmos DB for Table。 API for Table 是資料表儲存體的進階供應項目,可提供輸送量最佳化的資料表、全域散發,以及自動次要索引。

此文章說明如何建立資料表、儲存您的資料,以及對上述資料執行 CRUD 作業。 這些範例是以 Java 撰寫,並使用適用於 Java 的 Azure 資料表用戶端程式庫。 所涵蓋的案例包括「建立」、「列出」和「刪除」資料表,以及在資料表中「插入」、「查詢」、「修改」和「刪除」實體。 如需資料表的詳細資訊,請參閱 後續步驟 一節。

重要

支援資料表儲存體和 Azure Cosmos DB 資料表的最新版本 Azure 資料表用戶端程式庫為 12+

建立 Azure 服務帳戶

您可以使用 Azure 表格儲存體或 Azure Cosmos DB 來搭配使用表格。 若要深入瞭解這兩個服務中的資料表供應項目間的差異,請參閱 API for Table 概觀。 您必須為您要使用的服務建立帳戶。 下列各節說明如何建立 Azure 資料表儲存體和 Azure Cosmos DB 帳戶,不過您可以只使用其中一個。

建立 Azure 儲存體帳戶

建立 Azure 儲存體帳戶最簡單的方法,就是使用 Azure 入口網站。 若要深入了解,請參閱 建立儲存體帳戶

您也可以使用 Azure PowerShellAzure CLI 來建立 Azure 儲存體帳戶。

如果您不想在此時建立儲存體帳戶,也可以使用 Azure 儲存體模擬器在本機環境中執行並測試您的程式碼。 如需詳細資訊,請參閱使用 Azure 儲存體模擬器進行開發和測試

建立 Azure Cosmos DB 帳戶

如需建立 Azure Cosmos DB for Table 帳戶的相關指示,請參閱建立資料庫帳戶

建立 Java 應用程式

若要使用本文中的範例:

  1. 安裝 Java 開發套件 (JDK)
  2. 在您的 Azure 訂用帳戶中建立 Azure 儲存體帳戶或 Azure Cosmos DB 帳戶。
  3. 驗證您的開發系統符合 GitHub 上適用於 Java 的 Azure 資料表用戶端程式庫存放庫中所列的最低需求和相依性。
  4. 遵循指示以從該存放庫中下載適用於 Java 的 Azure 儲存體程式庫,並安裝在系統上。
  5. 建立使用本文中範例的 Java 應用程式。

設定您的應用程式以存取資料表儲存體

pom.xml 檔案的 dependencies 區段中新增下列項目:

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-data-tables</artifactId>
  <version>12.1.1</version>
</dependency>

然後,將下列 import 陳述式新增到您要在其中使用 Azure 資料表 API 來存取資料表的 Java 檔案頂端:

// Include the following imports to use table APIs
import com.azure.data.tables.TableClient;
import com.azure.data.tables.TableClientBuilder;
import com.azure.data.tables.TableServiceClient;
import com.azure.data.tables.TableServiceClientBuilder;
import com.azure.data.tables.models.ListEntitiesOptions;
import com.azure.data.tables.models.TableEntity;
import com.azure.data.tables.models.TableEntityUpdateMode;
import com.azure.data.tables.models.TableTransactionAction;
import com.azure.data.tables.models.TableTransactionActionType;

新增連接字串

您可以連線到 Azure 儲存體帳戶或 Azure Cosmos DB for Table 帳戶。 根據您使用的帳戶類型,取得連接字串。

新增 Azure 儲存體連接字串

Azure 資料表用戶端可以使用儲存體連接字串來儲存存取資料管理服務時所用的端點與認證。 在用戶端應用程式中執行時,您必須以下列格式提供儲存體連接字串,使用您儲存體帳戶的名稱以及 Azure 入口網站中針對該儲存體帳戶列出的主要存取索引鍵作為 AccountNameAccountKey 值。

本範例將示範如何宣告靜態欄位來存放連接字串:

// Define the connection-string with your values.
public final String connectionString =
    "DefaultEndpointsProtocol=http;" +
    "AccountName=your_storage_account;" +
    "AccountKey=your_storage_account_key;" +
    "EndpointSuffix=core.windows.net";

新增 Azure Cosmos DB for Table 連接字串

Azure Cosmos DB 帳戶會使用連接字串來儲存資料表端點和您的認證。 在用戶端應用程式中執行時,您必須以下列格式提供 Azure Cosmos DB 連接字串,使用您 Azure Cosmos DB 帳戶的名稱以及 Azure 入口網站中針對該帳戶列出的主要存取索引鍵作為 AccountNameAccountKey 值。

本範例將示範如何宣告靜態欄位來存放 Azure Cosmos DB 連接字串:

public final String connectionString =
    "DefaultEndpointsProtocol=https;" + 
    "AccountName=your_cosmosdb_account;" + 
    "AccountKey=your_account_key;" + 
    "TableEndpoint=https://your_endpoint;";

在 Azure 角色內執行的應用程式中,您可以將此字串儲存在服務設定檔 ServiceConfiguration.cscfg 中。 您可以透過呼叫 System.getenv 方法來存取它。 以下是從服務設定檔中名為 ConnectionStringSetting 元素取得連接字串的範例:

// Retrieve storage account from connection-string.
String connectionString = System.getenv("ConnectionString");

您也可以將連接字串儲存在專案的 config.properties 檔案中:

connectionString = DefaultEndpointsProtocol=https;AccountName=your_account;AccountKey=your_account_key;TableEndpoint=https://your_table_endpoint/

下列範例假設您已經使用這其中一個方法來取得儲存體連接字串。

建立表格

TableServiceClient 物件可讓您與資料表服務互動,以便建立、列出和刪除資料表。 下列程式碼會建立 TableServiceClient 物件,並使用它建立新的 TableClient 物件,其代表名為 Employees 的資料表。

try
{
    final String tableName = "Employees";

    // Create a TableServiceClient with a connection string.
    TableServiceClient tableServiceClient = new TableServiceClientBuilder()
        .connectionString(connectionString)
        .buildClient();

    // Create the table if it not exists.
    TableClient tableClient = tableServiceClient.createTableIfNotExists(tableName);

}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

列出資料表

若要取得資料表清單,請呼叫 TableServiceClient.listTables 方法來擷取可逐一查看的資料表名稱清單。

try
{
    // Create a TableServiceClient with a connection string.
    TableServiceClient tableServiceClient = new TableServiceClientBuilder()
        .connectionString(connectionString)
        .buildClient();

    // Loop through a collection of table names.
    tableServiceClient.listTables().forEach(tableItem -> 
        System.out.printf(tableItem.getName())
    );
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

將實體新增至資料表

下列程式碼會建立 TableEntity 類別的新執行個體,其中含有一些要儲存的客戶資料。 該程式碼會呼叫 TableClient 物件上的 upsertEntity 方法。 該方法會將新的客戶實體插入 Employees 資料表中,或取代實體 (如果已存在)。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
     TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Create a new employee TableEntity.
    String partitionKey = "Sales";
    String rowKey = "0001";
    Map<String, Object> personalInfo= new HashMap<>();
    personalInfo.put("FirstName", "Walter");
    personalInfo.put("LastName", "Harp");
    personalInfo.put("Email", "Walter@contoso.com");
    personalInfo.put("PhoneNumber", "425-555-0101");
    TableEntity employee = new TableEntity(partitionKey, rowKey).setProperties(personalInfo);
        
    // Upsert the entity into the table
    tableClient.upsertEntity(employee);
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

插入一批實體

您可以在單一寫入操作中,插入實體批次至資料表服務。 下列程式碼會建立 List<TableTransactionAction> 物件,然後在其中新增三個 upsert 作業。 藉由建立新的 TableEntity 物件、設定其屬性,然後在物件 TableClient 上呼叫 submitTransaction 方法,即可新增每個作業。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    String partitionKey = "Sales";
    List<TableTransactionAction> tableTransactionActions = new ArrayList<>();
    
    Map<String, Object> personalInfo1 = new HashMap<>();
    personalInfo1.put("FirstName", "Jeff");
    personalInfo1.put("LastName", "Smith");
    personalInfo1.put("Email", "Jeff@contoso.com");
    personalInfo1.put("PhoneNumber", "425-555-0104");
    
    // Create an entity to add to the table.
    tableTransactionActions.add(new TableTransactionAction(
        TableTransactionActionType.UPSERT_MERGE,
        new TableEntity(partitionKey, "0001")
            .setProperties(personalInfo1)
    ));
    
    Map<String, Object> personalInfo2 = new HashMap<>();
    personalInfo2.put("FirstName", "Ben");
    personalInfo2.put("LastName", "Johnson");
    personalInfo2.put("Email", "Ben@contoso.com");
    personalInfo2.put("PhoneNumber", "425-555-0102");
    
    // Create another entity to add to the table.
    tableTransactionActions.add(new TableTransactionAction(
        TableTransactionActionType.UPSERT_MERGE,
        new TableEntity(partitionKey, "0002")
            .setProperties(personalInfo2)
    ));
    
    Map<String, Object> personalInfo3 = new HashMap<>();
    personalInfo3.put("FirstName", "Denise");
    personalInfo3.put("LastName", "Rivers");
    personalInfo3.put("Email", "Denise@contoso.com");
    personalInfo3.put("PhoneNumber", "425-555-0103");
    
    // Create a third entity to add to the table.
    tableTransactionActions.add(new TableTransactionAction(
        TableTransactionActionType.UPSERT_MERGE,
        new TableEntity(partitionKey, "0003")
            .setProperties(personalInfo3)
    ));

    // Submit transaction on the "Employees" table.
    tableClient.submitTransaction(tableTransactionActions);
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

以下是批次操作的一些注意事項:

  • 您可以在單一批次中最多執行 100 個插入、刪除、合併、取代、插入或合併,以及插入或取代操作的任意組合。
  • 當擷取操作是批次中的唯一操作時,批次操作可以包含擷取操作。
  • 單一批次操作中的所有實體必須具有相同的資料分割索引鍵。
  • 一個批次操作的資料裝載限制為 4MB。

擷取資料分割中的所有實體

若要查詢資料表以取得分割區中的實體,可以使用 ListEntitiesOptions。 呼叫 ListEntitiesOptions.setFilter 以在特定資料表上建立傳回指定結果類型的查詢。 下列程式碼會指定篩選分割區索引鍵為 Sales 的實體。 使用對 TableClient 物件上的 listEntities 呼叫來執行查詢時,它會傳回 TableEntityIterator。 然後,您可以使用 "ForEach" 迴圈中傳回的 Iterator 來取用結果。 此程式碼會將查詢結果中每個實體的欄位列印至主控台。

try
{
    // Define constants for filters.
    final String PARTITION_KEY = "PartitionKey";
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Create a filter condition where the partition key is "Sales".
    ListEntitiesOptions options = new ListEntitiesOptions().setFilter(PARTITION_KEY + " eq 'Sales'");

    // Loop through the results, displaying information about the entities.
    tableClient.listEntities(options, null, null).forEach(tableEntity -> {
        System.out.println(tableEntity.getPartitionKey() +
            " " + tableEntity.getRowKey() +
            "\t" + tableEntity.getProperty("FirstName") +
            "\t" + tableEntity.getProperty("LastName") +
            "\t" + tableEntity.getProperty("Email") +
            "\t" + tableEntity.getProperty("PhoneNumber"));
    });
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

擷取資料分割中某個範圍的實體

如果您不想要查詢資料分割中的所有實體,可以在篩選中使用比較運算子來指定範圍。 下列程式碼會結合兩個篩選器,以取得分割區 Sales 中資料列索引鍵介於 '0001' 和 '0004' 之間的所有實體。 然後列印查詢結果。 如果您使用在本指南批次插入小節中新增至資料表的實體,則這時只會傳回兩個實體 (Ben Smith 及 Denise Smith)。

try
{
    // Define constants for filters.
    final String PARTITION_KEY = "PartitionKey";
    final String ROW_KEY = "RowKey";
    final String tableName = "Employees";

    // Create a TableServiceClient with a connection string.
    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Create a filter condition where the partition key is "Sales".
    ListEntitiesOptions options = new ListEntitiesOptions().setFilter(PARTITION_KEY + " eq 'Sales' AND " + ROW_KEY + " lt '0004' AND " + ROW_KEY + " gt '0001'");
    
    // Loop through the results, displaying information about the entities.
    tableClient.listEntities(options, null, null).forEach(tableEntity -> {
        System.out.println(tableEntity.getPartitionKey() +
            " " + tableEntity.getRowKey() +
            "\t" + tableEntity.getProperty("FirstName") +
            "\t" + tableEntity.getProperty("LastName") +
            "\t" + tableEntity.getProperty("Email") +
            "\t" + tableEntity.getProperty("PhoneNumber"));
    });
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

擷取單一實體

您可以撰寫查詢來擷取單一特定實體。 下列程式碼會搭配分割區索引鍵和資料列索引鍵參數呼叫 TableClient.getEntity 以擷取員工 "Jeff Smith" 的實體,而不是建立 ListEntitiesOptions 並使用篩選來達到同樣目的。 執行時,擷取操作只會傳回一個實體,而不是傳回一個集合。 如果沒有實體具有完全相符的分割區和資料列索引鍵,則會傳回 null 值。 若要從資料表服務中擷取單一實體,最快的方法是在查詢中同時指定資料分割索引鍵和資料列索引鍵。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Get the specific entity.
    TableEntity specificEntity = tableClient.getEntity("Sales", "0001");

    // Output the entity.
    if (specificEntity != null)
    {
        System.out.println(specificEntity.getPartitionKey() +
            " " + specificEntity.getRowKey() +
            "\t" + specificEntity.getProperty("FirstName") +
            "\t" + specificEntity.getProperty("LastName") +
            "\t" + specificEntity.getProperty("Email") +
            "\t" + specificEntity.getProperty("PhoneNumber"));
    }
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

修改實體

若要修改實體,請從資料表服務擷取它,對實體物件進行變更,然後以取代或合併操作將變更儲存回資料表服務。 下列程式碼會變更現有客戶的電話號碼。 與我們插入時呼叫 tableClient.upsertEntity 不同,此程式碼會呼叫 tableClient.updateEntity

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Get the specific entity.
    TableEntity specificEntity = tableClient.getEntity("Sales", "0001");

    // Specify a new phone number
    specificEntity.getProperties().put("PhoneNumber", "425-555-0105");

    // Update the specific entity
    tableClient.updateEntity(specificEntity, TableEntityUpdateMode.REPLACE);
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

查詢實體屬性的子集

一項資料表查詢可以只擷取實體的少數屬性。 這項稱為「投射」的技術可減少頻寬並提高查詢效能 (尤其是對大型實體而言)。 下列程式碼中的查詢會使用 ListEntitiesOptions.setSelect 方法,只傳回資料表中實體的電子郵件地址。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Create a filter condition that retrieves only the Email property.
    List<String> attributesToRetrieve = new ArrayList<>();
    attributesToRetrieve.add("Email");
    
    ListEntitiesOptions options = new ListEntitiesOptions().setSelect(attributesToRetrieve);

    // Loop through the results, displaying the Email values.
    tableClient.listEntities(options, null, null).forEach(tableEntity -> {
        System.out.println(tableEntity.getProperty("Email"));
    });
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

插入或取代實體

您經常會想要新增實體至資料表,但不知道它是否已在資料表中。 插入或取代作業可讓您提出單一要求。 該要求將插入實體 (如果實體不存在),或是取代現有實體 (如果實體存在)。 以先前的範例為基礎,下列程式碼會插入或取代 "Walter Harp" 的實體。 建立新實體之後,此程式碼會呼叫 TableClient.upsertEntity 方法。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Create a new table entity.
    Map<String, Object> properties = new HashMap<>();
    properties.put("FirstName", "Walter");
    properties.put("LastName", "Harp");
    properties.put("Email", "Walter@contoso.com");
    properties.put("PhoneNumber", "425-555-0101");
        
    TableEntity newEmployee = new TableEntity("Sales", "0004")
        .setProperties(properties);
        
    // Add the new customer to the Employees table.
    tableClient.upsertEntity(newEmployee);
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

刪除實體

您可以刪除實體,方法是透過 TableClient.deleteEntity 提供其分割區索引鍵和資料列索引鍵。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Delete the entity for partition key 'Sales' and row key '0001' from the table.
    tableClient.deleteEntity("Sales", "0001");
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

刪除資料表

最後,下列程式碼會從帳戶刪除資料表。 在您刪除資料表大約 40 秒後,便無法重新建立該資料表。

try
{
    final String tableName = "Employees";

    // Create a TableClient with a connection string and a table name.
    TableClient tableClient = new TableClientBuilder()
        .connectionString(connectionString)
        .tableName(tableName)
        .buildClient();

    // Delete the table and all its data.
    tableClient.deleteTable();
}
catch (Exception e)
{
    // Output the stack trace.
    e.printStackTrace();
}

提示

請查看 Azure 儲存體程式碼範例儲存機制

如需可供您下載和執行的簡易端對端 Azure 儲存體程式碼範例,請查看我們的 Azure 儲存體範例清單。

下一步

如需詳細資訊,請瀏覽適用於 Java 開發人員的 Azure