Início Rápido: criar um aplicativo da API para Table com o SDK do Java e o Azure Cosmos DB

APLICA-SE A: Table

Este guia de início rápido mostra como acessar a API de Tabela do Azure Cosmos DB em um aplicativo Java. A API de Tabela do Azure Cosmos DB é um armazenamento de dados sem esquema para que os aplicativos armazenem dados NoSQL estruturados na nuvem. Como os dados são armazenados sem esquema, as propriedades novas (colunas) são adicionadas automaticamente à tabela quando um objeto com um novo atributo é adicionado a ela.

Os aplicativos Java podem acessar a API de Tabela do Azure Cosmos DB usando a biblioteca de clientes de azure-data-tables.

Pré-requisitos

O aplicativo de exemplo é escrito no Spring Boot 2.6.4, você pode usar Visual Studio Code ou IntelliJ IDEA como um IDE.

Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

Aplicativo de exemplo

Você pode clonar ou baixar o aplicativo de exemplo deste tutorial no repositório https://github.com/Azure-Samples/msdocs-azure-data-tables-sdk-java. O repositório de amostras inclui um aplicativo de início e um aplicativo completo.

git clone https://github.com/Azure-Samples/msdocs-azure-data-tables-sdk-java

O aplicativo de exemplo usa dados meteorológicos para demonstrar os recursos da API de Tabela. Os objetos que representam as observações sobre o clima são armazenados e recuperados usando a API para Table, incluindo o armazenamento de objetos com propriedades adicionais para demonstrar os recursos sem esquema da API de Tabela.

Uma captura de tela do aplicativo concluído, que mostra os dados armazenados em uma tabela do Azure Cosmos DB usando a API de Tabela.

1 – Criar uma conta do Azure Cosmos DB

Primeiro, você precisa criar uma conta da API de Tabela do Azure Cosmos DB, que conterá as tabelas usadas no aplicativo. Para isso, você pode usar o portal do Azure, a CLI do Azure ou o Azure PowerShell.

Entre no portal do Azure e siga estas etapas para criar uma conta do Azure Cosmos DB.

Instruções Captura de tela
No Portal do Azure:
  1. Na caixa de pesquisa na parte superior do portal do Azure, insira "Azure Cosmos DB".
  2. No menu que aparece abaixo da barra de pesquisa, em Serviços, selecione o item com o rótulo Azure Cosmos DB.
Uma captura de tela que mostra como usar a caixa de pesquisa na barra de ferramentas superior para localizar as contas do Azure Cosmos DB no Azure.
Na página Azure Cosmos DB, selecione +Criar. Uma captura de tela que mostra o local do botão Criar na página de contas do Azure Cosmos DB no Azure.
Na página Selecionar opção de API, escolha a opção Tabela do Azure. Uma captura de tela mostrando a opção da Tabela do Azure como a opção correta para selecionar.
Na página Criar Conta do Azure Cosmos DB – Tabela do Azure, preencha o formulário da seguinte maneira.
  1. Crie um grupo de recursos para a conta de armazenamento chamada rg-msdocs-tables-sdk-demo selecionando o link Criar em Grupo de recursos.
  2. Dê o nome de cosmos-msdocs-tables-sdk-demo-XYZ à conta de armazenamento, no qual XYZ são três caracteres aleatórios para criar um nome de conta exclusivo. Os nomes de contas do Azure Cosmos DB devem ter entre 3 e 44 caracteres e podem conter apenas letras minúsculas, números ou o caractere de hífen (-).
  3. Selecione a região de sua conta de armazenamento.
  4. Selecione o desempenho Standard.
  5. Selecione Taxa de transferência provisionada para este exemplo em Modo de capacidade.
  6. Selecione Aplicar em Aplicar Desconto por Nível Gratuito para este exemplo.
  7. Clique no botão Examinar e criar na parte inferior da tela e depois selecione "Criar" na tela de resumo para criar a conta do Azure Cosmos DB. Esse processo pode levar vários minutos.
Uma captura de tela que mostra como preencher os campos na página de criação de conta do Azure Cosmos DB.

2 – Criar uma tabela

Em seguida, você precisa criar uma tabela em sua conta do Azure Cosmos DB para que o aplicativo use. Ao contrário de um banco de dados tradicional, você só precisa especificar o nome da tabela e não as propriedades (colunas). À medida que os dados são carregados na tabela, as propriedades (colunas) são criadas automaticamente conforme necessário.

No portal do Azure, siga as etapas a seguir para criar uma tabela dentro de sua conta do Azure Cosmos DB.

Instruções Captura de tela
Na página portal do Azure, navegue até a página de visão geral da conta do Azure Cosmos DB. Você pode navegar até a página de visão geral da sua conta do Azure Cosmos DB digitando o nome (cosmos-msdocs-tables-sdk-demo-XYZ) da sua conta do Azure Cosmos DB na barra de pesquisa superior e conferindo o título de recursos. Selecione o nome da sua conta do Azure Cosmos DB para acessar a página de visão geral. Uma captura de tela que mostra como usar a caixa de pesquisa na barra de ferramentas superior para localizar uma conta do Azure Cosmos DB.
Na página Visão geral, selecione + Adicionar Tabela. A caixa de diálogo Nova Tabela será exibida do lado direito da página. Uma captura de tela que mostra o local do botão Adicionar Tabela.
Na caixa de diálogo Nova Tabela, preencha o formulário a seguir.
  1. Insira o nome WeatherData para a ID da Tabela. Esse é o nome da tabela.
  2. Selecione Manual em Taxa de transferência de tabela (dimensionamento automático) para este exemplo.
  3. Use o valor padrão de 400 na RU/s estimada.
  4. Selecione o botão OK para criar a tabela.
Uma captura de tela que mostra a caixa de diálogo Nova Tabela para uma tabela do Azure Cosmos DB.

3 – Obter a cadeia de conexão do Azure Cosmos DB

Para acessar as tabelas no Azure Cosmos DB, o aplicativo precisará da cadeia de conexão de tabela da conta de Armazenamento do CosmosDB. Você pode conseguir a cadeia de conexão usando o portal do Azure, a CLI do Azure ou o Azure PowerShell.

Instruções Captura de tela
No lado esquerdo da página da conta do Azure Cosmos DB, localize o item de menu chamado Cadeia de Conexão no título Segurança e selecione-o. Você acessará uma página em que poderá recuperar a cadeia de conexão da conta de armazenamento. Uma captura de tela que mostra o local do link de cadeias de conexão na página do Azure Cosmos DB.
Copie o valor da CADEIA DE CONEXÃO PRIMÁRIA para usar no aplicativo. Uma captura de tela que mostra qual cadeia de conexão você deve selecionar e usar no aplicativo.

A cadeia de conexão da conta do Azure Cosmos DB é considerada um segredo de aplicativo, portanto, deve ser protegida como qualquer outro segredo de aplicativo ou senha. Este exemplo usa POM para armazenar a cadeia de conexão durante o desenvolvimento e disponibilizá-la ao aplicativo.

<profiles>
    <profile>
        <id>local</id>
        <properties>
            <azure.tables.connection.string>
                <![CDATA[YOUR-DATA-TABLES-SERVICE-CONNECTION-STRING]]>
            </azure.tables.connection.string>
            <azure.tables.tableName>WeatherData</azure.tables.tableName>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
</profiles>

4 – Incluir o pacote azure-data-tables

Para acessar a API de Tabela do Azure Cosmos DB em um aplicativo Java, inclua o pacote azure-data-tables.

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

5 – Configurar TableClient no TableServiceConfig.java

O SDK do Azure se comunica com o Azure usando objetos de cliente para executar operações diferentes no Azure. O objeto TableClient é usado para se comunicar com a API de Tabela do Azure Cosmos DB.

Normalmente, o aplicativo cria um único objeto TableClient por tabela para ser usado em todo o aplicativo. É recomendável indicar que um método produz um bean de objeto TableClient a ser gerenciado pelo contêiner Spring e como um singleton para fazer isso.

No arquivo TableServiceConfig.java do aplicativo, edite o método tableClientConfiguration() para que ele fique igual ao seguinte snippet de código:

@Configuration
public class TableServiceConfiguration {

    private static String TABLE_NAME;

    private static String CONNECTION_STRING;

    @Value("${azure.tables.connection.string}")
    public void setConnectionStringStatic(String connectionString) {
        TableServiceConfiguration.CONNECTION_STRING = connectionString;
    }

    @Value("${azure.tables.tableName}")
    public void setTableNameStatic(String tableName) {
        TableServiceConfiguration.TABLE_NAME = tableName;
    }

    @Bean
    public TableClient tableClientConfiguration() {
        return new TableClientBuilder()
                .connectionString(CONNECTION_STRING)
                .tableName(TABLE_NAME)
                .buildClient();
    }
    
}

Também é preciso adicionar o seguinte usando a instrução na parte superior do arquivo TableServiceConfig.java.

import com.azure.data.tables.TableClient;
import com.azure.data.tables.TableClientBuilder;

6 – Implementar operações de tabela do Azure Cosmos DB

Todas as operações de tabela do Azure Cosmos DB do aplicativo de amostra são implementadas na classe TablesServiceImpl, localizada no diretório Services. Você precisará importar o com.azure.data.tables pacote do SDK.

import com.azure.data.tables.TableClient;
import com.azure.data.tables.models.ListEntitiesOptions;
import com.azure.data.tables.models.TableEntity;
import com.azure.data.tables.models.TableTransactionAction;
import com.azure.data.tables.models.TableTransactionActionType;

No início da classe TableServiceImpl, adicione uma variável de membro do objeto TableClient e um construtor para permitir a injeção do objeto TableClient na classe.

@Autowired
private TableClient tableClient;

Obter linhas de uma tabela

A classe TableClient contém um método chamado listEntities, que permite selecionar linhas da tabela. Como este exemplo não passa nenhum parâmetro ao método, todas as linhas da tabela são selecionadas.

O método também aceita um parâmetro genérico do tipo TableEntity que especifica o modelo para o retorno dos dados de classe. Nesse caso, a classe interna TableEntity é usada, o que significa que o método listEntities retorna uma coleção PagedIterable<TableEntity> como resultados.

public List<WeatherDataModel> retrieveAllEntities() {
    List<WeatherDataModel> modelList = tableClient.listEntities().stream()
        .map(WeatherDataUtils::mapTableEntityToWeatherDataModel)
        .collect(Collectors.toList());
    return Collections.unmodifiableList(WeatherDataUtils.filledValue(modelList));
}

A classe TableEntity definida no pacote com.azure.data.tables.models tem propriedades para os valores de chave de partição e de chave de linha na tabela. Juntos, esses dois valores para uma chave exclusiva na linha na tabela. Neste aplicativo de exemplo, o nome da estação meteorológica (cidade) é armazenado na chave de partição, e a data/hora da observação é armazenada na chave de linha. Todas as outras propriedades (temperatura, umidade, velocidade do vento) são armazenadas em um dicionário no objeto TableEntity.

É uma prática comum mapear um objeto TableEntity para um objeto de sua própria definição. O aplicativo de exemplo define uma classe WeatherDataModel no diretório Models para essa finalidade. A classe tem propriedades para o nome da estação e a data de observação que serão associados à chave de partição e à chave de linha, com nomes mais significativos para esses valores. Em seguida, ela usa um dicionário para armazenar todas as outras propriedades no objeto. Esse é um padrão comum ao trabalhar com o armazenamento de tabelas, pois uma linha pode ter qualquer número de propriedades arbitrárias, e os objetos de modelo devem capturar todas elas. A classe também contém métodos para listar as propriedades dela.

public class WeatherDataModel {

    public WeatherDataModel(String stationName, String observationDate, OffsetDateTime timestamp, String etag) {
        this.stationName = stationName;
        this.observationDate = observationDate;
        this.timestamp = timestamp;
        this.etag = etag;
    }

    private String stationName;

    private String observationDate;

    private OffsetDateTime timestamp;

    private String etag;

    private Map<String, Object> propertyMap = new HashMap<String, Object>();

    public String getStationName() {
        return stationName;
    }

    public void setStationName(String stationName) {
        this.stationName = stationName;
    }

    public String getObservationDate() {
        return observationDate;
    }

    public void setObservationDate(String observationDate) {
        this.observationDate = observationDate;
    }

    public OffsetDateTime getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(OffsetDateTime timestamp) {
        this.timestamp = timestamp;
    }

    public String getEtag() {
        return etag;
    }

    public void setEtag(String etag) {
        this.etag = etag;
    }

    public Map<String, Object> getPropertyMap() {
        return propertyMap;
    }

    public void setPropertyMap(Map<String, Object> propertyMap) {
        this.propertyMap = propertyMap;
    }
}

O método mapTableEntityToWeatherDataModel é usado para mapear um objeto TableEntity para um objeto WeatherDataModel. O método mapTableEntityToWeatherDataModel mapeia diretamente as propriedades PartitionKey, RowKey, Timestamp e Etag, depois usa properties.keySet para iterar as demais propriedades no objeto TableEntity e mapeá-las ao objeto WeatherDataModel, exceto as propriedades que já foram mapeadas diretamente.

Edite o código no método mapTableEntityToWeatherDataModel para que fique igual ao bloco de código a seguir.

public static WeatherDataModel mapTableEntityToWeatherDataModel(TableEntity entity) {
    WeatherDataModel observation = new WeatherDataModel(
        entity.getPartitionKey(), entity.getRowKey(),
        entity.getTimestamp(), entity.getETag());
    rearrangeEntityProperties(observation.getPropertyMap(), entity.getProperties());
    return observation;
}

private static void rearrangeEntityProperties(Map<String, Object> target, Map<String, Object> source) {
    Constants.DEFAULT_LIST_OF_KEYS.forEach(key -> {
        if (source.containsKey(key)) {
            target.put(key, source.get(key));
        }
    });
    source.keySet().forEach(key -> {
        if (Constants.DEFAULT_LIST_OF_KEYS.parallelStream().noneMatch(defaultKey -> defaultKey.equals(key))
        && Constants.EXCLUDE_TABLE_ENTITY_KEYS.parallelStream().noneMatch(defaultKey -> defaultKey.equals(key))) {
            target.put(key, source.get(key));
        }
    });
}

Filtrar as linhas retornadas de uma tabela

Para filtrar as linhas retornadas de uma tabela, você pode passar uma cadeia de caracteres de filtro de estilo OData ao método listEntities. Por exemplo, para obter todas as leituras meteorológicas de Chicago entre a meia-noite de 1º de julho de 2021 e a meia-noite de 2 de julho de 2021 (inclusive), você passaria a cadeia de caracteres de filtro a seguir.

PartitionKey eq 'Chicago' and RowKey ge '2021-07-01 12:00 AM' and RowKey le '2021-07-02 12:00 AM'

Todos os operadores de filtro OData estão disponíveis no site do OData, na seção Opção de consulta do sistema do filtro

No aplicativo de exemplo, o objeto FilterResultsInputModel captura os critérios de filtro informados pelo usuário.

public class FilterResultsInputModel implements Serializable {

    private String partitionKey;

    private String rowKeyDateStart;

    private String rowKeyTimeStart;

    private String rowKeyDateEnd;

    private String rowKeyTimeEnd;

    private Double minTemperature;

    private Double maxTemperature;

    private Double minPrecipitation;

    private Double maxPrecipitation;

    public String getPartitionKey() {
        return partitionKey;
    }

    public void setPartitionKey(String partitionKey) {
        this.partitionKey = partitionKey;
    }

    public String getRowKeyDateStart() {
        return rowKeyDateStart;
    }

    public void setRowKeyDateStart(String rowKeyDateStart) {
        this.rowKeyDateStart = rowKeyDateStart;
    }

    public String getRowKeyTimeStart() {
        return rowKeyTimeStart;
    }

    public void setRowKeyTimeStart(String rowKeyTimeStart) {
        this.rowKeyTimeStart = rowKeyTimeStart;
    }

    public String getRowKeyDateEnd() {
        return rowKeyDateEnd;
    }

    public void setRowKeyDateEnd(String rowKeyDateEnd) {
        this.rowKeyDateEnd = rowKeyDateEnd;
    }

    public String getRowKeyTimeEnd() {
        return rowKeyTimeEnd;
    }

    public void setRowKeyTimeEnd(String rowKeyTimeEnd) {
        this.rowKeyTimeEnd = rowKeyTimeEnd;
    }

    public Double getMinTemperature() {
        return minTemperature;
    }

    public void setMinTemperature(Double minTemperature) {
        this.minTemperature = minTemperature;
    }

    public Double getMaxTemperature() {
        return maxTemperature;
    }

    public void setMaxTemperature(Double maxTemperature) {
        this.maxTemperature = maxTemperature;
    }

    public Double getMinPrecipitation() {
        return minPrecipitation;
    }

    public void setMinPrecipitation(Double minPrecipitation) {
        this.minPrecipitation = minPrecipitation;
    }

    public Double getMaxPrecipitation() {
        return maxPrecipitation;
    }

    public void setMaxPrecipitation(Double maxPrecipitation) {
        this.maxPrecipitation = maxPrecipitation;
    }
}

Quando o objeto é passado ao método retrieveEntitiesByFilter na classe TableServiceImpl, ele cria uma cadeia de caracteres de filtro para cada valor de propriedade não nulo. Em seguida, ele cria uma cadeia de caracteres de filtro combinada unindo todos os valores com uma cláusula "and". A cadeia de caracteres de filtro combinada é passada ao método listEntities no objeto TableClient e somente as linhas correspondentes à cadeia de caracteres de filtro são retornadas. Você pode usar um método semelhante no código para criar cadeias de caracteres de filtro adequadas a seu aplicativo.

public List<WeatherDataModel> retrieveEntitiesByFilter(FilterResultsInputModel model) {

    List<String> filters = new ArrayList<>();

    if (!StringUtils.isEmptyOrWhitespace(model.getPartitionKey())) {
        filters.add(String.format("PartitionKey eq '%s'", model.getPartitionKey()));
    }
    if (!StringUtils.isEmptyOrWhitespace(model.getRowKeyDateStart())
            && !StringUtils.isEmptyOrWhitespace(model.getRowKeyTimeStart())) {
        filters.add(String.format("RowKey ge '%s %s'", model.getRowKeyDateStart(), model.getRowKeyTimeStart()));
    }
    if (!StringUtils.isEmptyOrWhitespace(model.getRowKeyDateEnd())
            && !StringUtils.isEmptyOrWhitespace(model.getRowKeyTimeEnd())) {
        filters.add(String.format("RowKey le '%s %s'", model.getRowKeyDateEnd(), model.getRowKeyTimeEnd()));
    }
    if (model.getMinTemperature() != null) {
        filters.add(String.format("Temperature ge %f", model.getMinTemperature()));
    }
    if (model.getMaxTemperature() != null) {
        filters.add(String.format("Temperature le %f", model.getMaxTemperature()));
    }
    if (model.getMinPrecipitation() != null) {
        filters.add(String.format("Precipitation ge %f", model.getMinPrecipitation()));
    }
    if (model.getMaxPrecipitation() != null) {
        filters.add(String.format("Precipitation le %f", model.getMaxPrecipitation()));
    }

    List<WeatherDataModel> modelList = tableClient.listEntities(new ListEntitiesOptions()
        .setFilter(String.join(" and ", filters)), null, null).stream()
        .map(WeatherDataUtils::mapTableEntityToWeatherDataModel)
        .collect(Collectors.toList());
    return Collections.unmodifiableList(WeatherDataUtils.filledValue(modelList));
}

Inserir dados usando um objeto TableEntity

A maneira mais simples de adicionar dados a uma tabela é usar um objeto TableEntity. Neste exemplo, mapeamos os dados de um objeto de modelo de entrada para um objeto TableEntity. Mapeamos as propriedades no objeto de entrada que representam o nome da estação meteorológica e a data/hora de observação para as propriedades PartitionKey e RowKey, respectivamente, que juntas formam uma chave exclusiva para a linha na tabela. Em seguida, mapeamos as propriedades adicionais no objeto de modelo de entrada para propriedades de dicionário no objeto TableClient. Por fim, usamos o método createEntity do objeto TableClient para inserir dados na tabela.

Modifique a classe insertEntity do aplicativo de exemplo para conter o código a seguir.

public void insertEntity(WeatherInputModel model) {
    tableClient.createEntity(WeatherDataUtils.createTableEntity(model));
}

Executar upsert de dados usando um objeto TableEntity

Se você tentar inserir uma linha em uma tabela com uma combinação de chave de partição/chave de linha que já existe nessa tabela, você receberá um erro. Por isso, geralmente é melhor usar o método upsertEntity em vez de insertEntity ao adicionar linhas a uma tabela. Se a combinação de chave/linha de partição determinada já existir na tabela, o método upsertEntity atualizará a linha atual. Caso contrário, a linha será adicionada à tabela.

public void upsertEntity(WeatherInputModel model) {
    tableClient.upsertEntity(WeatherDataUtils.createTableEntity(model));
}

Inserir ou executar upsert de dados com propriedades variáveis

Esta é uma das vantagens de usar a API de Tabela do Azure Cosmos DB: se o objeto carregado em uma tabela contiver propriedades novas, elas serão adicionadas automaticamente à tabela e os valores serão armazenados no Azure Cosmos DB. Não é necessário executar instruções DDL como ALTER TABLE para adicionar colunas como em um banco de dados tradicional.

Com esse modelo, o aplicativo tem flexibilidade para lidar com fontes que adicionam dados ou modificam quais dados devem ser capturados ao longo do tempo, ou quando entradas diferentes fornecem dados diferentes ao aplicativo. No aplicativo de exemplo, podemos simular uma estação meteorológica que envia não apenas os dados meteorológicos base, mas também alguns outros valores. Quando um objeto com essas novas propriedades for armazenado na tabela pela primeira vez, as propriedades correspondentes (colunas) serão adicionadas automaticamente à tabela.

No aplicativo de exemplo, a classe ExpandableWeatherObject é criada em torno de um dicionário interno para dar suporte para qualquer conjunto de propriedades no objeto. Essa classe representa um padrão típico no qual um objeto precisa conter um conjunto arbitrário de propriedades.

public class ExpandableWeatherObject {

    private String stationName;

    private String observationDate;

    private Map<String, Object> propertyMap = new HashMap<String, Object>();

    public String getStationName() {
        return stationName;
    }

    public void setStationName(String stationName) {
        this.stationName = stationName;
    }

    public String getObservationDate() {
        return observationDate;
    }

    public void setObservationDate(String observationDate) {
        this.observationDate = observationDate;
    }

    public Map<String, Object> getPropertyMap() {
        return propertyMap;
    }

    public void setPropertyMap(Map<String, Object> propertyMap) {
        this.propertyMap = propertyMap;
    }

    public boolean containsProperty(String key) {
        return this.propertyMap.containsKey(key);
    }

    public Object getPropertyValue(String key) {
        return containsProperty(key) ? this.propertyMap.get(key) : null;
    }

    public void putProperty(String key, Object value) {
        this.propertyMap.put(key, value);
    }

    public List<String> getPropertyKeys() {
        List<String> list = Collections.synchronizedList(new ArrayList<String>());
        Iterator<String> iterators = this.propertyMap.keySet().iterator();
        while (iterators.hasNext()) {
            list.add(iterators.next());
        }
        return Collections.unmodifiableList(list);
    }

    public Integer getPropertyCount() {
        return this.propertyMap.size();
    }
}

Para inserir ou executar upsert nesse objeto usando a API para Table, mapeie as propriedades do objeto expansível para um objeto TableEntity e use o método createEntity ou upsertEntity no objeto TableClient, conforme apropriado.

public void insertExpandableEntity(ExpandableWeatherObject model) {
    tableClient.createEntity(WeatherDataUtils.createTableEntity(model));
}

public void upsertExpandableEntity(ExpandableWeatherObject model) {
    tableClient.upsertEntity(WeatherDataUtils.createTableEntity(model));
}

Atualizar uma entidade

Para atualizar entidades, chame o método updateEntity do objeto TableClient. Como uma entidade (linha) armazenada usando a API de Tabela pode conter qualquer conjunto arbitrário de propriedades, geralmente é útil criar um objeto de atualização com base em um objeto dictionary semelhante ao ExpandableWeatherObject discutido anteriormente. Nesse caso, a única diferença é a adição da propriedade etag, que é usada para controle de simultaneidade durante as atualizações.

public class UpdateWeatherObject {

    private String stationName;

    private String observationDate;

    private String etag;

    private Map<String, Object> propertyMap = new HashMap<String, Object>();

    public String getStationName() {
        return stationName;
    }

    public void setStationName(String stationName) {
        this.stationName = stationName;
    }

    public String getObservationDate() {
        return observationDate;
    }

    public void setObservationDate(String observationDate) {
        this.observationDate = observationDate;
    }

    public String getEtag() {
        return etag;
    }

    public void setEtag(String etag) {
        this.etag = etag;
    }

    public Map<String, Object> getPropertyMap() {
        return propertyMap;
    }

    public void setPropertyMap(Map<String, Object> propertyMap) {
        this.propertyMap = propertyMap;
    }
}

No aplicativo de exemplo, esse objeto é passado ao método updateEntity na classe TableServiceImpl. O método primeiro carrega a entidade atual da API de Tabela com o método getEntity no TableClient. Em seguida, ele atualiza esse objeto de entidade e usa o método updateEntity para salvar as atualizações no banco de dados. Observe que o método updateEntity usa a Etag atual do objeto para garantir que ele não foi alterado após o carregamento inicial. Se você quiser atualizar a entidade mesmo assim, passe o valor etag ao método updateEntity.

public void updateEntity(UpdateWeatherObject model) {
    TableEntity tableEntity = tableClient.getEntity(model.getStationName(), model.getObservationDate());
    Map<String, Object> propertiesMap = model.getPropertyMap();
    propertiesMap.keySet().forEach(key -> tableEntity.getProperties().put(key, propertiesMap.get(key)));
    tableClient.updateEntity(tableEntity);
}

Remover uma entidade

Para remover uma entidade de uma tabela, chame o método deleteEntity no objeto TableClient com a chave de partição e a chave de linha do objeto.

public void deleteEntity(WeatherInputModel model) {
    tableClient.deleteEntity(model.getStationName(),
            WeatherDataUtils.formatRowKey(model.getObservationDate(), model.getObservationTime()));
}

7 – Executar o código

Execute o aplicativo de exemplo para interagir com a API de Tabela do Azure Cosmos DB. Na primeira vez que você executar o aplicativo, não haverá dados porque a tabela estará vazia. Use qualquer um dos botões na parte superior do aplicativo para adicionar dados à tabela.

Uma captura de tela do aplicativo que mostra o local dos botões usados para inserir dados no Azure Cosmos DB usando a API de Tabela.

Quando você seleciona o botão Inserir Usando Entidade de Tabela, é aberta uma caixa de diálogo para a inserção ou o upsert de uma nova linha usando um objeto TableEntity.

Uma captura de tela do aplicativo que mostra a caixa de diálogo para inserir dados usando um objeto TableEntity.

Quando você seleciona o botão Inserir usando Dados Expansíveis, é aberta uma caixa de diálogo para a inserção de um objeto com propriedades personalizadas. Isso demonstra que a API de Tabela do Azure Cosmos DB adiciona automaticamente propriedades (colunas) à tabela quando necessário. Use o botão Adicionar Campo Personalizado para adicionar uma ou mais propriedades novas e demonstrar essa funcionalidade.

Uma captura de tela do aplicativo que mostra a caixa de diálogo para inserir dados usando um objeto com campos personalizados.

Use o botão Inserir dados de exemplo para carregar alguns dados de exemplo na tabela do Azure Cosmos DB.

Uma captura de tela do aplicativo que mostra o local do botão de inserção de dados de exemplo.

Selecione o item Filtrar Resultados no menu superior para abrir a página Resultados do Filtro. Nesta página, preencha os critérios de filtro para demonstrar como criar uma cláusula de filtro e passá-la à API de Tabela do Azure Cosmos DB.

Uma captura de tela do aplicativo que mostra a página de resultados do filtro e realça o item de menu usado para navegar até a página.

Limpar os recursos

Quando você terminar o aplicativo de exemplo, remova todos os recursos do Azure relacionados a este artigo de sua conta do Azure. Para fazer isso, exclua o grupo de recursos.

Para excluir um grupo de recursos, siga as instruções a seguir no portal do Azure.

Instruções Captura de tela
Para acessar o grupo de recursos, na barra de pesquisa, digite o nome do grupo de recursos. Na guia Grupos de Recursos, selecione o nome do grupo de recursos. Captura de tela que mostra como pesquisar um grupo de recursos.
Selecione Excluir grupo de recursos na barra de ferramentas, na parte superior da página do grupo de recursos. Uma captura de tela que mostra a localização do botão Excluir grupo de recursos.
Uma caixa de diálogo será exibida à direita da tela solicitando que você confirme a exclusão do grupo de recursos.
  1. Digite o nome completo do grupo de recursos na caixa de texto para confirmar a exclusão, conforme instruído.
  2. Selecione o botão Excluir na parte inferior da página.
Uma captura de tela que mostra a caixa de diálogo de confirmação para excluir um grupo de recursos.

Próximas etapas

Neste início rápido, você aprendeu como criar uma conta do BD Cosmos do Azure, como criar uma tabela usando o Data Explorer e como executar um aplicativo. Agora você pode consultar os dados usando a API de Tabela.