Início Rápido: Utilizar Java e JDBC com Base de Dados do Azure para MySQL

APLICA-SE A: Base de Dados do Azure para MySQL - Servidor Único

Importante

Base de Dados do Azure para MySQL - O Servidor Único está no caminho de descontinuação. Recomendamos vivamente que atualize para o Base de Dados do Azure para MySQL – Servidor Flexível. Para obter mais informações sobre como migrar para Base de Dados do Azure para MySQL – Servidor Flexível, consulte O que está a acontecer ao Base de Dados do Azure para MySQL Servidor Único?

Este artigo demonstra como criar uma aplicação de exemplo que utiliza Java e JDBC para armazenar e obter informações no Base de Dados do Azure para MySQL.

O JDBC é a API Java padrão para ligar a bases de dados relacionais tradicionais.

Neste artigo, vamos incluir dois métodos de autenticação: autenticação do Azure Active Directory (Azure AD) e autenticação MySQL. O separador Sem palavra-passe mostra a autenticação Azure AD e o separador Palavra-passe mostra a autenticação MySQL.

Azure AD autenticação é um mecanismo para ligar a Base de Dados do Azure para MySQL através de identidades definidas no Azure AD. Com Azure AD autenticação, pode gerir identidades de utilizador da base de dados e outros serviços Microsoft numa localização central, o que simplifica a gestão de permissões.

A autenticação MySQL utiliza contas armazenadas no MySQL. Se optar por utilizar palavras-passe como credenciais para as contas, estas credenciais serão armazenadas na user tabela. Uma vez que estas palavras-passe estão armazenadas no MySQL, terá de gerir a rotação das palavras-passe.

Pré-requisitos

  • Uma conta do Azure. Se não tiver uma, obtenha uma avaliação gratuita.
  • Azure Cloud Shell ou CLI do Azure. Recomendamos que o Azure Cloud Shell para que tenha sessão iniciada automaticamente e tenha acesso a todas as ferramentas necessárias.
  • Um Java Development Kit suportado, versão 8 (incluído no Azure Cloud Shell).
  • A ferramenta de compilação do Apache Maven .
  • Cliente da linha de comandos MySQL. Pode ligar ao servidor com a ferramenta de linha de comandos mysql.exe com o Azure Cloud Shell. Em alternativa, pode utilizar a linha de comandos mysql no seu ambiente local.

Preparar o ambiente de trabalho

Primeiro, configure algumas variáveis de ambiente. No Azure Cloud Shell, execute os seguintes comandos:

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=demo
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_MYSQL_AD_NON_ADMIN_USERNAME=demo-non-admin
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
export CURRENT_USERNAME=$(az ad signed-in-user show --query userPrincipalName -o tsv)
export CURRENT_USER_OBJECTID=$(az ad signed-in-user show --query id -o tsv)

Substitua os marcadores de posição pelos seguintes valores, que são utilizados ao longo deste artigo:

  • <YOUR_DATABASE_SERVER_NAME>: o nome do servidor MySQL, que deve ser exclusivo em todo o Azure.
  • <YOUR_AZURE_REGION>: a região do Azure que irá utilizar. Pode utilizar a região eastus por predefinição, mas recomendamos que configure uma região mais próxima do local onde vive. Pode ver a lista completa de regiões disponíveis ao introduzir az account list-locations.
  • <YOUR_LOCAL_IP_ADDRESS>: o endereço IP do seu computador local, a partir do qual irá executar a sua aplicação. Uma forma conveniente de encontrá-lo é abrir whatismyip.akamai.com.

Em seguida, crie um grupo de recursos com o seguinte comando:

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

Criar uma instância da Base de Dados do Azure para MySQL

Criar um servidor MySQL e configurar o utilizador administrador

A primeira coisa que vai criar é um servidor MySQL gerido.

Nota

Pode ler informações mais detalhadas sobre a criação de servidores MySQL no Início Rápido: Criar um servidor Base de Dados do Azure para MySQL com o portal do Azure.

Se estiver a utilizar a CLI do Azure, execute o seguinte comando para se certificar de que tem permissões suficientes:

az login --scope https://graph.microsoft.com/.default

Em seguida, execute o seguinte comando para criar o servidor:

az mysql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --location $AZ_LOCATION \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --output tsv

Em seguida, execute o seguinte comando para definir o Azure AD utilizador administrador:

az mysql server ad-admin create \
    --resource-group $AZ_RESOURCE_GROUP \
    --server-name $AZ_DATABASE_SERVER_NAME \
    --display-name $CURRENT_USERNAME \
    --object-id $CURRENT_USER_OBJECTID

Importante

Ao definir o administrador, é adicionado um novo utilizador ao servidor Base de Dados do Azure para MySQL com permissões de administrador completas. Só pode criar um Azure AD administrador por servidor MySQL. A seleção de outro utilizador substituirá o administrador de Azure AD existente configurado para o servidor.

Este comando cria um pequeno servidor MySQL e define o administrador do Active Directory para o utilizador com sessão iniciada.

Configurar uma regra de firewall para o servidor MySQL

As instâncias das Bases de Dados do Azure para MySQL estão protegidas por predefinição. Estas instâncias têm uma firewall que não permite qualquer ligação de entrada. Para poder utilizar a base de dados, tem de adicionar uma regra de firewall que permita que o endereço IP local aceda ao servidor da base de dados.

Uma vez que configurou o endereço IP local no início deste artigo, pode abrir a firewall do servidor ao executar o seguinte comando:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --server $AZ_DATABASE_SERVER_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    --output tsv

Se estiver a ligar ao servidor MySQL a partir do Subsistema Windows para Linux (WSL) num computador Windows, terá de adicionar o ID de anfitrião WSL à firewall.

Obtenha o endereço IP do computador anfitrião ao executar o seguinte comando no WSL:

cat /etc/resolv.conf

Copie o endereço IP após o termo nameservere, em seguida, utilize o seguinte comando para definir uma variável de ambiente para o Endereço IP WSL:

AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

Em seguida, utilize o seguinte comando para abrir a firewall do servidor na sua aplicação baseada em WSL:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip-wsl \
    --server $AZ_DATABASE_SERVER_NAME \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Configurar uma base de dados MySQL

O servidor MySQL que criou anteriormente está vazio. Utilize o seguinte comando para criar uma nova base de dados.

az mysql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --server-name $AZ_DATABASE_SERVER_NAME \
    --output tsv

Criar um utilizador não administrador do MySQL e conceder permissão

Em seguida, crie um utilizador não administrador e conceda todas as permissões à base de dados.

Nota

Pode ler informações mais detalhadas sobre a criação de utilizadores do MySQL em Criar utilizadores no Base de Dados do Azure para MySQL.

Crie um script SQL chamado create_ad_user.sql para criar um utilizador não administrador. Adicione os seguintes conteúdos e guarde-o localmente:

export AZ_MYSQL_AD_NON_ADMIN_USERID=$CURRENT_USER_OBJECTID

cat << EOF > create_ad_user.sql
SET aad_auth_validate_oids_in_tenant = OFF;

CREATE AADUSER '$AZ_MYSQL_AD_NON_ADMIN_USERNAME' IDENTIFIED BY '$AZ_MYSQL_AD_NON_ADMIN_USERID';

GRANT ALL PRIVILEGES ON $AZ_DATABASE_NAME.* TO '$AZ_MYSQL_AD_NON_ADMIN_USERNAME'@'%';

FLUSH privileges;

EOF

Em seguida, utilize o seguinte comando para executar o script SQL para criar o Azure AD utilizador não administrador:

mysql -h $AZ_DATABASE_SERVER_NAME.mysql.database.azure.com --user $CURRENT_USERNAME@$AZ_DATABASE_SERVER_NAME --enable-cleartext-plugin --password=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken) < create_ad_user.sql

Agora, utilize o seguinte comando para remover o ficheiro de script do SQL temporário:

rm create_ad_user.sql

Criar um novo projeto Java

Com o seu IDE favorito, crie um novo projeto Java com Java 8 ou superior. Crie um ficheiro pom.xml no respetivo diretório de raiz e adicione os seguintes conteúdos:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-identity-extensions</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

Este ficheiro é um ficheiro do Apache Maven que configura o seu projeto para utilizar o Java 8 e um controlador MySQL recente para Java.

Preparar um ficheiro de configuração para ligar ao Base de Dados do Azure para MySQL

Execute o seguinte script no diretório de raiz do projeto para criar um ficheiro src/main/resources/database.properties e adicionar detalhes de configuração:

mkdir -p src/main/resources && touch src/main/resources/database.properties

cat << EOF > src/main/resources/database.properties
url=jdbc:mysql://${AZ_DATABASE_SERVER_NAME}.mysql.database.azure.com:3306/${AZ_DATABASE_NAME}?sslMode=REQUIRED&serverTimezone=UTC&defaultAuthenticationPlugin=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin&authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin
user=${AZ_MYSQL_AD_NON_ADMIN_USERNAME}@${AZ_DATABASE_SERVER_NAME}
EOF

Nota

Se estiver a utilizar a classe MysqlConnectionPoolDataSource como a origem de dados na sua aplicação, remova "defaultAuthenticationPlugin=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin" no URL.

mkdir -p src/main/resources && touch src/main/resources/database.properties

cat << EOF > src/main/resources/database.properties
url=jdbc:mysql://${AZ_DATABASE_SERVER_NAME}.mysql.database.azure.com:3306/${AZ_DATABASE_NAME}?sslMode=REQUIRED&serverTimezone=UTC&authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin
user=${AZ_MYSQL_AD_NON_ADMIN_USERNAME}@${AZ_DATABASE_SERVER_NAME}
EOF

Nota

A propriedade de url?serverTimezone=UTC configuração foi acrescentada para indicar ao controlador JDBC para utilizar o formato de data UTC (ou Hora Universal Coordenada) ao ligar à base de dados. Caso contrário, o servidor Java não utilizaria o mesmo formato de data que a base de dados, o que resultaria num erro.

Criar um ficheiro SQL para gerar o esquema da base de dados

Em seguida, irá utilizar um ficheiro src/main/resources/schema.sql para criar um esquema de base de dados. Crie esse ficheiro e, em seguida, adicione os seguintes conteúdos:

touch src/main/resources/schema.sql

cat << EOF > src/main/resources/schema.sql
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
EOF

Codificar a aplicação

Ligue-se à base de dados

Em seguida, adicione o código Java que utilizará o JDBC para armazenar e obter dados do servidor MySQL.

Crie um ficheiro src/main/java/DemoApplication.java e adicione os seguintes conteúdos:

package com.example.demo;

import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;

import java.sql.*;
import java.util.*;
import java.util.logging.Logger;

public class DemoApplication {

    private static final Logger log;

    static {
        System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$-7s] %5$s %n");
        log =Logger.getLogger(DemoApplication.class.getName());
    }

    public static void main(String[] args) throws Exception {
        log.info("Loading application properties");
        Properties properties = new Properties();
        properties.load(DemoApplication.class.getClassLoader().getResourceAsStream("database.properties"));

        log.info("Connecting to the database");
        Connection connection = DriverManager.getConnection(properties.getProperty("url"), properties);
        log.info("Database connection test: " + connection.getCatalog());

        log.info("Create database schema");
        Scanner scanner = new Scanner(DemoApplication.class.getClassLoader().getResourceAsStream("schema.sql"));
        Statement statement = connection.createStatement();
        while (scanner.hasNextLine()) {
            statement.execute(scanner.nextLine());
        }

        /* Prepare to store and retrieve data from the MySQL server.
        Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
        insertData(todo, connection);
        todo = readData(connection);
        todo.setDetails("congratulations, you have updated data!");
        updateData(todo, connection);
        deleteData(todo, connection);
        */

        log.info("Closing database connection");
        connection.close();
        AbandonedConnectionCleanupThread.uncheckedShutdown();
    }
}

Este código Java irá utilizar as propriedades database.properties e os ficheiros schema.sql que criou anteriormente. Depois de ligar ao servidor MySQL, pode criar um esquema para armazenar os seus dados.

Neste ficheiro, pode ver que comentou métodos para inserir, ler, atualizar e eliminar dados. Irá implementar esses métodos no resto deste artigo e poderá descompactá-los um após o outro.

Nota

As credenciais da base de dados são armazenadas nas propriedades de utilizador e palavra-passe do ficheiro database.properties . Essas credenciais são utilizadas ao executar DriverManager.getConnection(properties.getProperty("url"), properties);, uma vez que o ficheiro de propriedades é transmitido como um argumento.

Nota

A AbandonedConnectionCleanupThread.uncheckedShutdown(); linha no final é um comando do controlador MySQL para destruir um thread interno ao encerrar a aplicação. Pode ignorar esta linha com segurança.

Agora pode executar esta classe principal com a sua ferramenta favorita:

  • Com o IDE, deverá conseguir clicar com o botão direito do rato na classe DemoApplication e executá-la.
  • Com o Maven, pode executar a aplicação com o seguinte comando: mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication".

A aplicação deve ligar-se ao Base de Dados do Azure para MySQL, criar um esquema de base de dados e, em seguida, fechar a ligação. Deverá ver um resultado semelhante ao seguinte exemplo nos registos da consola:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Closing database connection

Criar uma classe de domínio

Crie uma nova Todo classe Java, junto à DemoApplication classe e adicione o seguinte código:

package com.example.demo;

public class Todo {

    private Long id;
    private String description;
    private String details;
    private boolean done;

    public Todo() {
    }

    public Todo(Long id, String description, String details, boolean done) {
        this.id = id;
        this.description = description;
        this.details = details;
        this.done = done;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    @Override
    public String toString() {
        return "Todo{" +
                "id=" + id +
                ", description='" + description + '\'' +
                ", details='" + details + '\'' +
                ", done=" + done +
                '}';
    }
}

Esta classe é um modelo de domínio mapeado na tabela que criou ao todo executar o script schema.sql .

Inserir dados no Base de Dados do Azure para MySQL

No ficheiro src/main/java/DemoApplication.java , após o método principal, adicione o seguinte método para inserir dados na base de dados:

private static void insertData(Todo todo, Connection connection) throws SQLException {
    log.info("Insert data");
    PreparedStatement insertStatement = connection
            .prepareStatement("INSERT INTO todo (id, description, details, done) VALUES (?, ?, ?, ?);");

    insertStatement.setLong(1, todo.getId());
    insertStatement.setString(2, todo.getDescription());
    insertStatement.setString(3, todo.getDetails());
    insertStatement.setBoolean(4, todo.isDone());
    insertStatement.executeUpdate();
}

Agora, pode anular o comentário das duas linhas seguintes no main método :

Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);

Executar a classe principal deve agora produzir o seguinte resultado:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Insert data
[INFO   ] Closing database connection

Ler dados de Base de Dados do Azure para MySQL

Em seguida, leia os dados anteriormente inseridos para validar que o código funciona corretamente.

No ficheiro src/main/java/DemoApplication.java , depois do método , adicione o insertData seguinte método para ler dados da base de dados:

private static Todo readData(Connection connection) throws SQLException {
    log.info("Read data");
    PreparedStatement readStatement = connection.prepareStatement("SELECT * FROM todo;");
    ResultSet resultSet = readStatement.executeQuery();
    if (!resultSet.next()) {
        log.info("There is no data in the database!");
        return null;
    }
    Todo todo = new Todo();
    todo.setId(resultSet.getLong("id"));
    todo.setDescription(resultSet.getString("description"));
    todo.setDetails(resultSet.getString("details"));
    todo.setDone(resultSet.getBoolean("done"));
    log.info("Data read from the database: " + todo.toString());
    return todo;
}

Agora, pode anular o comentário da seguinte linha no main método :

todo = readData(connection);

Executar a classe principal deve agora produzir o seguinte resultado:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Insert data
[INFO   ] Read data
[INFO   ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO   ] Closing database connection

Atualizar dados no Base de Dados do Azure para MySQL

Em seguida, atualize os dados que inseriu anteriormente.

Ainda no ficheiro src/main/java/DemoApplication.java , após o método , adicione o readData seguinte método para atualizar os dados dentro da base de dados:

private static void updateData(Todo todo, Connection connection) throws SQLException {
    log.info("Update data");
    PreparedStatement updateStatement = connection
            .prepareStatement("UPDATE todo SET description = ?, details = ?, done = ? WHERE id = ?;");

    updateStatement.setString(1, todo.getDescription());
    updateStatement.setString(2, todo.getDetails());
    updateStatement.setBoolean(3, todo.isDone());
    updateStatement.setLong(4, todo.getId());
    updateStatement.executeUpdate();
    readData(connection);
}

Agora, pode anular o comentário das duas linhas seguintes no main método :

todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);

Executar a classe principal deve agora produzir o seguinte resultado:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Insert data
[INFO   ] Read data
[INFO   ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO   ] Update data
[INFO   ] Read data
[INFO   ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO   ] Closing database connection

Eliminar dados no Base de Dados do Azure para MySQL

Por fim, elimine os dados que inseriu anteriormente.

Ainda no ficheiro src/main/java/DemoApplication.java , após o método , adicione o updateData seguinte método para eliminar dados dentro da base de dados:

private static void deleteData(Todo todo, Connection connection) throws SQLException {
    log.info("Delete data");
    PreparedStatement deleteStatement = connection.prepareStatement("DELETE FROM todo WHERE id = ?;");
    deleteStatement.setLong(1, todo.getId());
    deleteStatement.executeUpdate();
    readData(connection);
}

Agora, pode anular o comentário da seguinte linha no main método :

deleteData(todo, connection);

Executar a classe principal deve agora produzir o seguinte resultado:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Insert data
[INFO   ] Read data
[INFO   ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO   ] Update data
[INFO   ] Read data
[INFO   ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO   ] Delete data
[INFO   ] Read data
[INFO   ] There is no data in the database!
[INFO   ] Closing database connection

Limpar os recursos

Parabéns! Criou uma aplicação Java que utiliza JDBC para armazenar e obter dados de Base de Dados do Azure para MySQL.

Para limpar todos os recursos utilizados durante este início rápido, elimine o grupo de recursos com o seguinte comando:

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes

Passos seguintes