如何使用適用於 Java 的 Azure 資料表用戶端連結庫

適用於: Table

提示

本文的內容適用於 Azure 資料表記憶體和適用於資料表的 Azure Cosmos DB。 Table 的 API 是數據表記憶體的進階供應專案,可提供輸送量優化的數據表、全域散發和自動次要索引。

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

重要

支援資料表 儲存體 和 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 的指示,請參閱 建立資料庫帳戶

建立 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。 根據您使用的帳戶類型取得 連接字串。

新增 Azure 儲存體 連接字串

Azure 資料表用戶端可以使用記憶體 連接字串 來儲存端點和認證,以存取數據管理服務。 在用戶端應用程式中執行時,您必須以下列格式提供 儲存體 連接字串,使用 儲存體 帳戶的名稱,以及 AccountName 和 AccountKey 值 Azure 入口網站 中列出的 儲存體 帳戶的主要存取密鑰。

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

// 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

Azure Cosmos DB 帳戶會使用 連接字串 來儲存數據表端點和您的認證。 在用戶端應用程式中執行時,您必須使用 Azure Cosmos DB 帳戶的名稱,以及 AccountName 和 AccountKey 值 Azure 入口網站 中列出的帳戶主要存取密鑰,提供下列格式的 Azure Cosmos DB 連接字串。

此範例示範如何宣告靜態字段來保存 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 呼叫來存取它。 以下是從服務組態檔中名為 連線 ionString 的 Setting 元素取得 連接字串 的範例:

// 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物件可讓您與Tables服務互動,以便建立、列出及刪除數據表。 下列程式代碼會 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 個插入、刪除、合併、取代、插入或合併,以及在任意組合中插入或取代作業。
  • 如果批次作業是批次中唯一的作業,則批次作業可以有擷取作業。
  • 單一批次作業中的所有實體都必須具有相同的數據分割索引鍵。
  • 批次作業僅限於 4 MB 的數據承載。

擷取分割中的所有實體

若要查詢資料分割中實體的數據表,您可以使用 ListEntitiesOptions。 呼叫 ListEntitiesOptions.setFilter ,在傳回指定結果類型的特定數據表上建立查詢。 下列程式代碼會指定實體的篩選,其中 Sales 是分割區索引鍵。 當查詢在物件上呼叫 listEntities 來執行 TableClient 時,它會傳 Iterator 回 的 TableEntity。 接著 Iterator ,您可以使用 「ForEach」 循環中傳回的 來取用結果。 此程式代碼會將查詢結果中每個實體的欄位列印至主控台。

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();
}

擷取分割中某範圍的實體

如果您不想查詢分割區中的所有實體,請在篩選中使用比較運算符來指定範圍。 下列程式代碼結合兩個篩選條件,以在 '0001' 和 '0004' 之間取得數據分割中的所有 Sales 實體。 然後,它會列印查詢結果。 如果您使用本指南批次插入區段中新增至數據表的實體,這次只會傳回兩個實體(Ben 和 Denise)。

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.updateEntity,而不是像我們一樣呼叫 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();

    // 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。