Início Rápido: Criar uma API para a aplicação Tabela com o SDK Java e o Azure Cosmos DB

APLICA-SE A: Tabela

Este início rápido mostra como aceder à API de Tabelas do Azure Cosmos DB a partir de uma aplicação Java. A API de Tabelas do Azure Cosmos DB é um arquivo de dados sem esquemas que permite que as aplicações armazenem dados NoSQL estruturados na cloud. Uma vez que os dados são armazenados num design sem esquema, são adicionadas automaticamente novas propriedades (colunas) à tabela quando um objeto com um novo atributo é adicionado à tabela.

As aplicações Java podem aceder à API de Tabelas do Azure Cosmos DB com a biblioteca de cliente azure-data-tables .

Pré-requisitos

A aplicação de exemplo é escrita no Spring Boot 2.6.4, pode utilizar o Visual Studio Code ou o IntelliJ IDEA como um IDE.

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

Aplicação de exemplo

A aplicação de exemplo para este tutorial pode ser clonada ou transferida a partir do repositório https://github.com/Azure-Samples/msdocs-azure-data-tables-sdk-java. Tanto uma aplicação inicial como uma aplicação concluída estão incluídas no repositório de exemplo.

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

A aplicação de exemplo utiliza dados meteorológicos como exemplo para demonstrar as capacidades da API de Tabelas. Os objetos que representam observações meteorológicas são armazenados e obtidos com a API para Tabela, incluindo o armazenamento de objetos com propriedades adicionais para demonstrar as capacidades sem esquema da API de Tabelas.

Captura de ecrã da aplicação concluída a mostrar os dados armazenados numa tabela do Azure Cosmos DB com a API de Tabela.

1 - Criar uma conta do Azure Cosmos DB

Primeiro, tem de criar uma conta da API de Tabelas do Azure Cosmos DB que irá conter as tabelas utilizadas na sua aplicação. Isto pode ser feito com o portal do Azure, a CLI do Azure ou Azure PowerShell.

Inicie sessão no portal do Azure e siga estes passos para criar uma conta do Azure Cosmos DB.

Instruções Captura de ecrã
No portal do Azure:
  1. Na barra de pesquisa na parte superior do portal do Azure, introduza "Azure Cosmos DB".
  2. No menu apresentado abaixo da barra de pesquisa, em Serviços, selecione o item com o nome Azure Cosmos DB.
Captura de ecrã a mostrar como utilizar a caixa de pesquisa na barra de ferramentas superior para encontrar contas do Azure Cosmos DB no Azure.
Na página do Azure Cosmos DB , selecione +Criar. Captura de ecrã a mostrar a localização do botão Criar na página contas do Azure Cosmos DB no Azure.
Na página Selecionar opção de API, selecione a opção Tabela do Azure . Captura de ecrã a mostrar a opção Tabela do Azure como a opção correta a selecionar.
Na página Criar Conta do Azure Cosmos DB – Tabela do Azure , preencha o formulário da seguinte forma.
  1. Crie um novo grupo de recursos para a conta de armazenamento com o nome rg-msdocs-tables-sdk-demo ao selecionar a ligação Criar novo em Grupo de recursos.
  2. Atribua à sua conta de armazenamento um nome de cosmos-msdocs-tables-sdk-demo-XYZ onde XYZ são três carateres aleatórios para criar um nome de conta exclusivo. Os nomes das contas do Azure Cosmos DB têm de ter entre 3 e 44 carateres de comprimento e podem conter apenas letras minúsculas, números ou o caráter de hífen (-).
  3. Selecione a região para a sua conta de armazenamento.
  4. Selecione Desempenho padrão .
  5. Selecione Débito aprovisionado para este exemplo em Modo de capacidade.
  6. Selecione Aplicar em Aplicar Desconto de Escalão Gratuito para este exemplo.
  7. Selecione o botão Rever + criar na parte inferior do ecrã e, em seguida, selecione "Criar" no ecrã de resumo para criar a sua conta do Azure Cosmos DB. Este processo pode demorar vários minutos.
Captura de ecrã a mostrar como preencher os campos na página de criação da Conta do Azure Cosmos DB.

2 - Criar uma tabela

Em seguida, tem de criar uma tabela na sua conta do Azure Cosmos DB para a sua aplicação utilizar. Ao contrário de uma base de dados tradicional, só precisa de especificar o nome da tabela e não as propriedades (colunas) na tabela. À medida que os dados são carregados para a tabela, as propriedades (colunas) serão criadas automaticamente conforme necessário.

Na portal do Azure, conclua os seguintes passos para criar uma tabela dentro da sua conta do Azure Cosmos DB.

Instruções Captura de ecrã
Na portal do Azure, navegue para a página de descrição geral da conta do Azure Cosmos DB. Pode navegar para a página de descrição geral da sua conta do Azure Cosmos DB ao escrever o nome (cosmos-msdocs-tables-sdk-demo-XYZ) da sua conta do Azure Cosmos DB na barra de pesquisa superior e procurar no cabeçalho dos recursos. Selecione o nome da sua conta do Azure Cosmos DB para aceder à página de descrição geral. Captura de ecrã a mostrar como utilizar a caixa de pesquisa na barra de ferramentas superior para encontrar a sua conta do Azure Cosmos DB.
Na página de descrição geral, selecione +Adicionar Tabela. A caixa de diálogo Nova Tabela irá deslizar para fora do lado direito da página. Captura de ecrã a mostrar a localização do botão Adicionar Tabela.
Na caixa de diálogo Nova Tabela , preencha o formulário da seguinte forma.
  1. Introduza o nome WeatherData para o ID da Tabela. Este é o nome da tabela.
  2. Selecione Manual em Débito da tabela (dimensionamento automático) para este exemplo.
  3. Utilize o valor predefinido de 400 nas RU/s estimadas.
  4. Selecione o botão OK para criar a tabela.
Uma captura de ecrã a mostrar como caixa de diálogo Nova Tabela para uma tabela do Azure Cosmos DB.

3 - Obter a cadeia de ligação do Azure Cosmos DB

Para aceder às tabelas no Azure Cosmos DB, a aplicação precisará da cadeia de ligação da tabela para a conta de Armazenamento do CosmosDB. A cadeia de ligação pode ser obtida com o portal do Azure, a CLI do Azure ou Azure PowerShell.

Instruções Captura de ecrã
No lado esquerdo da página da conta do Azure Cosmos DB, localize o item de menu denominado Cadeia de Ligação no cabeçalho Definições e selecione-o. Será levado para uma página onde pode obter a cadeia de ligação da conta de armazenamento. Captura de ecrã a mostrar a localização da ligação das cadeias de ligação na página do Azure Cosmos DB.
Copie o valor CADEIA DE LIGAÇÃO PRIMÁRIA para utilizar na sua aplicação. Captura de ecrã a mostrar a cadeia de ligação a selecionar e utilizar na sua aplicação.

A cadeia de ligação da sua conta do Azure Cosmos DB é considerada um segredo da aplicação e tem de ser protegida como qualquer outro segredo ou palavra-passe da aplicação. Este exemplo utiliza o POM para armazenar a cadeia de ligação durante o desenvolvimento e disponibilizá-la à aplicação.

<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 aceder à API de Tabelas do Azure Cosmos DB a partir de uma aplicação 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 o cliente tabela em TableServiceConfig.java

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

Normalmente, uma aplicação cria um único objeto TableClient por tabela para ser utilizada em toda a aplicação. Recomenda-se que indique que um método produz um objeto TableClient bean para ser gerido pelo contentor Spring e como singleton para o conseguir.

TableServiceConfig.java No ficheiro da aplicação, edite o tableClientConfiguration() método para corresponder ao seguinte fragmento 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 terá de adicionar a seguinte instrução using na parte superior do TableServiceConfig.java ficheiro.

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 para a aplicação de exemplo são implementadas na TablesServiceImpl classe localizada no diretório Serviços . Terá de 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 TableServiceImpl classe, adicione uma variável de membro para o objeto TableClient e um construtor para permitir que o objeto TableClient seja injetado na classe .

@Autowired
private TableClient tableClient;

Obter linhas de uma tabela

A classe TableClient contém um método denominado listEntities que lhe permite selecionar linhas da tabela. Neste exemplo, uma vez que não estão a ser transmitidos parâmetros para o método , todas as linhas serão selecionadas na tabela.

O método também utiliza um parâmetro genérico do tipo TableEntity que especifica que os dados da classe de modelo serão devolvidos como. Neste caso, é utilizada a classe incorporada TableEntity , o que significa que o listEntities método devolverá uma PagedIterable<TableEntity> coleção 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 com.azure.data.tables.models pacote tem propriedades para os valores da chave de partição e da chave de linha na tabela. Em conjunto, estes dois valores para uma chave exclusiva para a linha na tabela. Neste exemplo de aplicação, 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, humidade, velocidade do vento) são armazenadas num dicionário no TableEntity objeto.

É prática comum mapear um objeto TableEntity para um objeto da sua própria definição. A aplicação de exemplo define uma classe WeatherDataModel no diretório Modelos para esta finalidade. Esta classe tem propriedades para o nome da estação e a data de observação a que a chave de partição e a chave de linha serão mapeados, fornecendo nomes de propriedade mais significativos para estes valores. Em seguida, utiliza um dicionário para armazenar todas as outras propriedades no objeto. Este é um padrão comum ao trabalhar com o Armazenamento de tabelas, uma vez que uma linha pode ter qualquer número de propriedades arbitrárias e queremos que os nossos objetos de modelo sejam capazes de capturar todas elas. Esta classe também contém métodos para listar as propriedades na classe .

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 mapTableEntityToWeatherDataModel método é utilizado para mapear um objeto TableEntity para um WeatherDataModel objeto. O mapTableEntityToWeatherDataModel método mapeia diretamente as PartitionKeypropriedades , RowKey, Timestampe e Etag , em seguida, utiliza o properties.keySet para iterar sobre as outras propriedades no TableEntity objeto e mapeá-las para o WeatherDataModel objeto, menos as propriedades que já foram mapeadas diretamente.

Edite o código no mapTableEntityToWeatherDataModel método para corresponder ao seguinte bloco de código.

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 linhas devolvidas de uma tabela

Para filtrar as linhas devolvidas de uma tabela, pode transmitir uma cadeia de filtro de estilo OData para o método listEntities . Por exemplo, se quisesse 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), passaria a seguinte cadeia de filtro.

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

Pode ver todos os operadores de filtro OData no site OData na secção Opção Filtrar Consulta do Sistema

Na aplicação de exemplo, o FilterResultsInputModel objeto foi concebido para capturar os critérios de filtro fornecidos pelo utilizador.

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 este objeto é transmitido para o retrieveEntitiesByFilter método na TableServiceImpl classe , cria uma cadeia de filtro para cada valor de propriedade não nulo. Em seguida, cria uma cadeia de filtro combinada ao associar todos os valores com uma cláusula "e". Esta cadeia de filtro combinada é transmitida para o método listEntities no objeto TableClient e só serão devolvidas linhas que correspondam à cadeia de filtro. Pode utilizar um método semelhante no seu código para construir cadeias de filtro adequadas, conforme exigido pela sua aplicação.

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 com um objeto TableEntity

A forma mais simples de adicionar dados a uma tabela é através de um objeto TableEntity . Neste exemplo, os dados são mapeados de um objeto de modelo de entrada para um objeto TableEntity . As propriedades no objeto de entrada que representa o nome da estação meteorológica e a data/hora de observação são mapeadas para as PartitionKey propriedades e RowKey), respetivamente, que, em conjunto, formam uma chave exclusiva para a linha na tabela. Em seguida, as propriedades adicionais no objeto de modelo de entrada são mapeadas para as propriedades do dicionário no objeto TableClient . Por fim, o método createEntity no objeto TableClient é utilizado para inserir dados na tabela.

Modifique a insertEntity classe na aplicação de exemplo para conter o seguinte código.

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

Upsert data using a TableEntity object (Upsert data using a TableEntity object)

Se tentar inserir uma linha numa tabela com uma combinação de teclas de chave de partição/linha que já existe nessa tabela, receberá um erro. Por este motivo, muitas vezes é preferível utilizar upsertEntity em vez do insertEntity método ao adicionar linhas a uma tabela. Se a combinação de teclas de linha/chave de partição especificada já existir na tabela, o método upsertEntity atualizará a linha existente. Caso contrário, a linha será adicionada à tabela.

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

Inserir ou upsertar dados com propriedades variáveis

Uma das vantagens de utilizar a API de Tabelas do Azure Cosmos DB é que, se um objeto a ser carregado para uma tabela contiver novas propriedades, essas propriedades são adicionadas automaticamente à tabela e aos valores armazenados no Azure Cosmos DB. Não é necessário executar instruções DDL como ALTER TABLE adicionar colunas como numa base de dados tradicional.

Este modelo dá flexibilidade à sua aplicação ao lidar com origens de dados que podem adicionar ou modificar os dados que precisam de ser capturados ao longo do tempo ou quando entradas diferentes fornecem dados diferentes à sua aplicação. Na aplicação de exemplo, podemos simular uma estação meteorológica que envia não só os dados meteorológicos de base, mas também alguns valores adicionais. Quando um objeto com estas novas propriedades é armazenado na tabela pela primeira vez, as propriedades correspondentes (colunas) serão automaticamente adicionadas à tabela.

Na aplicação de exemplo, a ExpandableWeatherObject classe é criada em torno de um dicionário interno para suportar qualquer conjunto de propriedades no objeto. Esta classe representa um padrão típico para quando um objeto precisa de 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 upser tal objeto com a API para Tabela, mapeie as propriedades do objeto expansível para um objeto TableEntity e utilize os métodos createEntity ou upsertEntity no objeto TableClient conforme adequado.

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

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

Atualizar uma entidade

As entidades podem ser atualizadas ao chamar o método updateEntity no objeto TableClient . Uma vez que uma entidade (linha) armazenada com a API de Tabelas pode conter qualquer conjunto arbitrário de propriedades, muitas vezes é útil criar um objeto de atualização baseado num objeto de dicionário semelhante ao ExpandableWeatherObject abordado anteriormente. Neste caso, a única diferença é a adição de uma etag propriedade que é utilizada para o controlo 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;
    }
}

Na aplicação de exemplo, este objeto é transmitido para o updateEntity método na TableServiceImpl classe . Primeiro, este método carrega a entidade existente a partir da API de Tabelas com o método getEntity no TableClient. Em seguida, atualiza esse objeto de entidade e utiliza o updateEntity método para guardar as atualizações na base de dados. Tenha em atenção como o método updateEntity utiliza o Etag atual do objeto para garantir que o objeto não foi alterado desde que foi inicialmente carregado. Se quiser atualizar a entidade independentemente disso, poderá transmitir um valor de etag para o updateEntity método .

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 a aplicação de exemplo para interagir com a API de Tabelas do Azure Cosmos DB. Quando executar a aplicação pela primeira vez, não haverá dados porque a tabela está vazia. Utilize qualquer um dos botões na parte superior da aplicação para adicionar dados à tabela.

Uma captura de ecrã da aplicação a mostrar a localização dos botões utilizados para inserir dados no Azure Cosmos DB com a API de Tabela.

Selecionar o botão Inserir com a Entidade de Tabela abre uma caixa de diálogo que lhe permite inserir ou inserir uma nova linha com um TableEntity objeto.

Uma captura de ecrã da aplicação a mostrar a caixa de diálogo utilizada para inserir dados com um objeto TableEntity.

Selecionar o botão Inserir com Dados Expansíveis apresenta uma caixa de diálogo que lhe permite inserir um objeto com propriedades personalizadas, demonstrando como a API de Tabelas do Azure Cosmos DB adiciona automaticamente propriedades (colunas) à tabela quando necessário. Utilize o botão Adicionar Campo Personalizado para adicionar uma ou mais novas propriedades e demonstrar esta capacidade.

Uma captura de ecrã da aplicação a mostrar a caixa de diálogo utilizada para inserir dados com um objeto com campos personalizados.

Utilize o botão Inserir Dados de Exemplo para carregar alguns dados de exemplo para a tabela do Azure Cosmos DB.

Uma captura de ecrã da aplicação a mostrar a localização do botão de inserção de dados de exemplo.

Selecione o item Filtrar Resultados no menu superior a ser levado para a página Filtrar Resultados. Nesta página, preencha os critérios de filtro para demonstrar como uma cláusula de filtro pode ser criada e transmitida à API de Tabelas do Azure Cosmos DB.

Captura de ecrã da aplicação a mostrar a página de resultados do filtro e a realçar o item de menu utilizado para navegar para a página.

Limpar os recursos

Quando tiver terminado a aplicação de exemplo, deverá remover todos os recursos do Azure relacionados com este artigo da sua conta do Azure. Pode fazê-lo ao eliminar o grupo de recursos.

Um grupo de recursos pode ser eliminado com a portal do Azure ao fazer o seguinte.

Instruções Captura de ecrã
Para aceder ao grupo de recursos, na barra de pesquisa, escreva o nome do grupo de recursos. Em seguida, no separador Grupos de Recursos , selecione o nome do grupo de recursos. Uma captura de ecrã a mostrar como procurar um grupo de recursos.
Selecione Eliminar grupo de recursos na barra de ferramentas na parte superior da página do grupo de recursos. Captura de ecrã a mostrar a localização do botão Eliminar grupo de recursos.
Será apresentada uma caixa de diálogo à direita do ecrã a pedir-lhe para confirmar a eliminação do grupo de recursos.
  1. Escreva o nome completo do grupo de recursos na caixa de texto para confirmar a eliminação conforme indicado.
  2. Selecione o botão Eliminar na parte inferior da página.
Captura de ecrã a mostrar a caixa de diálogo de confirmação para eliminar um grupo de recursos.

Passos seguintes

Neste guia de introdução, aprendeu a criar uma conta do Azure Cosmos DB, a criar uma tabela com o Data Explorer e a executar uma aplicação. Agora, pode consultar os seus dados com a API para Tabela.