Como usar a biblioteca de cliente do Azure Tables para Java

APLICA-SE A: Tabela

Gorjeta

O conteúdo deste artigo aplica-se ao armazenamento de Tabela do Azure e ao Azure Cosmos DB para Tabela. A API for Table é uma oferta premium para armazenamento de tabelas que oferece tabelas otimizadas para taxa de transferência, distribuição global e índices secundários automáticos.

Este artigo mostra como criar tabelas, armazenar seus dados e executar operações CRUD nesses dados. Os exemplos são escritos em Java e usam a biblioteca de cliente de Tabelas do Azure para Java. Os cenários abrangidos incluem a criação, a listagem e a eliminação de tabelas, bem como a inserção, a consulta, a modificação e a eliminação de entidades numa tabela. Para obter mais informações sobre as tabelas, veja a secção Passos seguintes.

Importante

A última versão da biblioteca de cliente do Azure Tables com suporte ao Armazenamento de Tabela e à Tabela do Azure Cosmos DB é 12+.

Criar uma conta de serviço do Azure

Você pode trabalhar com tabelas usando o armazenamento de tabela do Azure ou o Azure Cosmos DB. Para saber mais sobre as diferenças entre as ofertas de tabela nesses dois serviços, consulte a Visão geral da API para tabela. Terá de criar uma conta para o serviço que quer utilizar. As seções a seguir mostram como criar o armazenamento de tabela do Azure e a conta do Azure Cosmos DB, no entanto, você pode usar apenas um deles.

Criar uma conta de armazenamento do Azure

A maneira mais fácil de criar uma conta de armazenamento do Azure é usando o portal do Azure. Para saber mais, veja Criar uma conta de armazenamento.

Também pode criar uma conta de armazenamento do Azure com o Azure PowerShell ou a CLI do Azure.

Se preferir não criar uma conta de armazenamento neste momento, você também pode usar o Emulador de Armazenamento do Azure para executar e testar seu código em um ambiente local. Para obter mais informações, consulte Usar o emulador de armazenamento do Azure para desenvolvimento e teste.

Criar uma conta do Azure Cosmos DB

Para obter instruções sobre como criar uma conta do Azure Cosmos DB for Table, consulte Criar uma conta de banco de dados.

Criar uma aplicação Java

Para usar os exemplos neste artigo:

  1. Instale o Java Development Kit (JDK).
  2. Crie uma conta de armazenamento do Azure ou uma conta do Azure Cosmos DB na sua subscrição do Azure.
  3. Verifique se seu sistema de desenvolvimento atende aos requisitos mínimos e dependências listados na biblioteca de cliente do Azure Tables para repositório Java no GitHub.
  4. Siga as instruções para baixar e instalar as Bibliotecas de Armazenamento do Azure para Java em seu sistema a partir desse repositório.
  5. Crie um aplicativo Java que use os exemplos neste artigo.

Configurar seu aplicativo para acessar o Armazenamento de Tabela

Adicione a seguinte entrada à secção do dependencies seu ficheiro pom.xml:

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

Em seguida, adicione as seguintes import instruções à parte superior do arquivo Java onde você deseja usar as APIs de Tabelas do Azure para acessar tabelas:

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

Adicione sua cadeia de conexão

Você pode se conectar à conta de armazenamento do Azure ou à conta do Azure Cosmos DB for Table. Obtenha a cadeia de conexão com base no tipo de conta que você está usando.

Adicionar uma cadeia de conexão do Armazenamento do Azure

Um cliente de Tabelas do Azure pode usar uma cadeia de conexão de armazenamento para armazenar pontos de extremidade e credenciais para acessar serviços de gerenciamento de dados. Ao executar em um aplicativo cliente, você deve fornecer a cadeia de conexão de Armazenamento no seguinte formato, usando o nome da sua conta de Armazenamento e a chave de acesso Primária para a conta de Armazenamento listada no portal do Azure para os valores AccountName e AccountKey.

Este exemplo mostra como pode declarar um campo estático para conter a cadeia de ligação:

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

Adicionar uma cadeia de conexão do Azure Cosmos DB para Tabela

As contas do Azure Cosmos DB utilizam uma cadeia de ligação para armazenar o ponto final da tabela e as suas credenciais. Ao executar em um aplicativo cliente, você deve fornecer a cadeia de conexão do Azure Cosmos DB no formato a seguir, usando o nome da sua conta do Azure Cosmos DB e a chave de acesso primária para a conta listada no portal do Azure para os valores AccountName e AccountKey.

Este exemplo mostra como pode declarar um campo estático para conter a cadeia de ligação do Azure Cosmos DB:

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

Em um aplicativo em execução dentro de uma função no Azure, você pode armazenar essa cadeia de caracteres no arquivo de configuração do serviço, ServiceConfiguration.cscfg. Você pode acessá-lo com uma chamada para o System.getenv método. Aqui está um exemplo de como obter a cadeia de conexão de um elemento Setting chamado ConnectionString no arquivo de configuração de serviço:

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

Também pode armazenar a cadeia de ligação no ficheiro config.properties do seu projeto:

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

Os exemplos seguintes partem do princípio de que utilizou um destes métodos para obter a cadeia de ligação de armazenamento.

Criar uma tabela

Um TableServiceClient objeto permite que você interaja com o serviço Tabelas para criar, listar e excluir tabelas. O código a seguir cria um TableServiceClient objeto e o usa para criar um novo TableClient objeto, que representa uma tabela chamada 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();
}

Listar as tabelas

Para obter uma lista de tabelas, chame o TableServiceClient.listTables método para recuperar uma lista iterável de nomes de tabelas.

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

Adicionar uma entidade a uma tabela

O código a seguir cria uma nova instância da classe com alguns dados do TableEntity cliente a serem armazenados. O código chama o upsertEntity método no TableClient objeto. Esse método insere a nova entidade do cliente na Employees tabela ou substitui a entidade se ela já existir.

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

Inserir um lote de entidades

Pode inserir um lote de entidades no serviço Tabela numa operação de escrita. O código a seguir cria um List<TableTransactionAction> objeto e, em seguida, adiciona três operações upsert a ele. Cada operação é adicionada criando um novo TableEntity objeto, definindo suas propriedades e, em seguida, chamando o submitTransaction método no TableClient objeto.

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

Algumas coisas a salientar nas operações de lote:

  • Pode realizar até cem operações de inserir, eliminar, unir, substituir, inserir ou intercalar e inserir ou substituir em qualquer combinação num lote individual.
  • As operações em lote podem ter uma operação de obter se for a única operação no lote.
  • Todas as entidades numa única operação em lote têm de ter a mesma chave de partição.
  • Uma operação em lote está limitada a um payload de dados de 4 MB.

Obter todas as entidades numa partição

Para consultar uma tabela para entidades em uma partição, você pode usar um ListEntitiesOptionsarquivo . Chamada ListEntitiesOptions.setFilter para criar uma consulta em uma tabela específica que retorna um tipo de resultado especificado. O código a seguir especifica um filtro para entidades onde Sales é a chave de partição. Quando a consulta é executada TableClient com uma chamada para listEntities no objeto, ela retorna um Iterator de TableEntity. Em seguida, você pode usar o Iterator retornado em um loop "ForEach" para consumir os resultados. Este código imprime os campos de cada entidade nos resultados da consulta para a consola.

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

Obter um intervalo de entidades numa partição

Se você não quiser consultar todas as entidades em uma partição, especifique um intervalo usando operadores de comparação em um filtro. O código a seguir combina dois filtros para obter todas as entidades na partição Sales com uma chave de linha entre '0001' e '0004'. Depois, imprime os resultados da consulta. Se você usar as entidades adicionadas à tabela na seção de inserção de lote deste guia, apenas duas entidades serão retornadas desta vez (Ben e 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();
}

Obter uma única entidade

Pode escrever uma consulta para obter uma entidade única e específica. O código a seguir chama TableClient.getEntity com parâmetros de chave de partição e chave de linha para recuperar a entidade para o funcionário "Jeff Smith", em vez de criar um ListEntitiesOptions e usar filtros para fazer a mesma coisa. Quando é executada, a operação de obtenção devolve apenas uma entidade em vez de uma coleção. Um null valor será retornado se nenhuma entidade tiver uma correspondência exata de partição e chave de linha. Especificar as chaves de partição e da fila numa consulta é a forma mais rápida de obter uma única entidade a partir do serviço Tabela.

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

Modificar uma entidade

Para modificar uma entidade, obtenha-a a partir do serviço Tabela, faça alterações ao objeto da entidade e guarde-as novamente no serviço Tabela com uma operação de substituição ou intercalação. O código seguinte altera o número de telefone de um cliente existente. Em vez de chamar tableClient.upsertEntity como fizemos para inserir, este código chama 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();
}

Consultar um subconjunto de propriedades de entidade

Uma consulta a uma tabela pode obter apenas algumas propriedades de uma entidade. Esta técnica, denominada projeção, reduz a largura de banda e pode melhorar o desempenho da consulta, especialmente para entidades grandes. A consulta no código a seguir usa o ListEntitiesOptions.setSelect método para retornar apenas os endereços de e-mail de entidades na tabela.

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

Inserir ou Substituir uma entidade

Em muitos casos, poderá querer adicionar uma entidade a uma tabela sem saber se já existe nessa tabela. Uma operação de inserção ou substituição permite que você faça uma única solicitação. Essa solicitação inserirá a entidade, se ela não existir, ou substituirá a existente, se existir. Continuando com os exemplos anteriores, o seguinte código insere ou substitui a entidade para "Walter Harp". Depois de criar uma nova entidade, esse código chama o TableClient.upsertEntity método.

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

Eliminar uma entidade

Você pode excluir uma entidade fornecendo sua chave de partição e chave de linha via 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();
}

Eliminar uma tabela

Finalmente, o código a seguir exclui uma tabela de uma conta. Cerca de 40 segundos depois de eliminar uma tabela, não é possível recriá-la.

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

Gorjeta

Veja o repositório de amostras de código do Armazenamento do Azure

Para obter exemplos de código de Armazenamento do Azure ponto a ponto fáceis de utilizar que pode transferir e executar, veja a nossa lista de Exemplos de Armazenamento do Azure.

Próximos passos

Para obter mais informações, visite Azure para programadores Java.