Usar o Java e o JDBC com o Banco de Dados do Azure para MySQL – Servidor Flexível

APLICA-SE A: Banco de Dados do Azure para MySQL – Servidor flexível

Este tópico demonstra como criar um aplicativo de exemplo que usa o Java e o JDBC para armazenar e recuperar informações no Servidor Flexível do Banco de Dados do Azure para MySQL.

O JDBC é a API Java padrão para se conectar a bancos de dados relacionais tradicionais.

Neste artigo, vamos incluir dois métodos de autenticação: autenticação do Microsoft Entra e autenticação do MySQL. A guia Sem senha mostra a autenticação do Microsoft Entra e a guia Senha mostra a autenticação do MySQL.

A autenticação Microsoft Entra é um mecanismo para se conectar ao Servidor Flexível do Banco de Dados do Azure para MySQL usando identidades definidas no Microsoft Entra ID. Com a autenticação do Microsoft Entra, você pode gerenciar as identidades de usuários do banco de dados e outros serviços da Microsoft em uma só localização central, o que simplifica o gerenciamento de permissões.

A autenticação do MySQL usa as contas armazenadas no MySQL. Se você optar por usar senhas como credenciais para as contas, essas credenciais serão armazenadas na tabela user. Como essas senhas são armazenadas no MySQL, você precisará gerenciar a rotação das senhas sozinho.

Pré-requisitos

Preparar o ambiente de trabalho

Primeiro, use o seguinte comando para configurar algumas variáveis de ambiente.

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_MYSQL_AD_NON_ADMIN_USERNAME=demo-non-admin
export AZ_USER_IDENTITY_NAME=<YOUR_USER_ASSIGNED_MANAGED_IDENTITY_NAME>
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 espaços reservados pelos seguintes valores, que são usados em todo este artigo:

  • <YOUR_DATABASE_NAME>: o nome da sua instância de Servidor Flexível do Banco de Dados do Azure para MySQL, que deve ser exclusiva no Azure.
  • <YOUR_AZURE_REGION>: A região do Azure que você usará. Você pode usar eastus por padrão, mas é recomendável configurar uma região mais próxima de onde você mora. Você pode ver a lista completa de regiões disponíveis ao digitar az account list-locations.
  • <YOUR_USER_ASSIGNED_MANAGED_IDENTITY_NAME>: o nome do servidor de identidade gerenciada atribuída pelo usuário, que deve ser exclusivo no Azure.

Em seguida, crie um grupo de recursos:

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

Criar uma instância do Banco de Dados do Azure para MySQL

Crie uma instância de Servidor Flexível do Banco de Dados do Azure para MySQL e configure um usuário administrador

A primeira coisa que você cria é uma instância de Servidor Flexível gerenciada do Banco de Dados do Azure para MySQL.

Observação

Você pode ler informações mais detalhadas sobre a criação de servidores MySQL em Criar uma instância de Servidor Flexível do Banco de Dados do Azure para MySQL usando o portal do Azure.

Se você estiver usando a CLI do Azure, execute o seguinte comando para garantir que ele tenha permissão suficiente:

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

Execute o comando a seguir para criar o servidor:

az mysql flexible-server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --yes \
    --output tsv

Execute o seguinte comando para criar uma identidade atribuída pelo usuário para atribuir:

az identity create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_USER_IDENTITY_NAME

Importante

Depois de criar a identidade atribuída pelo usuário, peça a um usuário com pelo menos a função de Administrador de funções com privilégios para conceder à identidade as seguintes permissões: User.Read.All, GroupMember.Read.All e Application.Read.ALL. Como alternativa, dê à identidade gerenciada atribuída pelo usuário a função Leitores de diretório. Para obter mais informações, consulte a seção Permissões da autenticação do Active Directory.

Execute o seguinte comando para atribuir a identidade ao Servidor Flexível do Banco de Dados do Azure para MySQL para criar o administrador do Microsoft Entra:

az mysql flexible-server identity assign \
    --resource-group $AZ_RESOURCE_GROUP \
    --server-name $AZ_DATABASE_NAME \
    --identity $AZ_USER_IDENTITY_NAME

Execute o seguinte comando para definir o usuário administrador do Microsoft Entra:

az mysql flexible-server ad-admin create \
    --resource-group $AZ_RESOURCE_GROUP \
    --server-name $AZ_DATABASE_NAME \
    --display-name $CURRENT_USERNAME \
    --object-id $CURRENT_USER_OBJECTID \
    --identity $AZ_USER_IDENTITY_NAME

Importante

Ao definir o administrador, um novo usuário é adicionado ao Servidor Flexível do Banco de Dados do Azure para MySQL com permissões completas de administrador. Apenas um administrador do Microsoft Entra pode ser criado por instância de Servidor Flexível do Banco de Dados do Azure para MySQL e a seleção de outro substituirá o administrador do Microsoft Entra existente configurado para o servidor.

Esse comando cria uma pequena instância de Servidor Flexível do Banco de Dados do Azure para MySQL e define o administrador do Active Directory para o usuário conectado.

A instância de Servidor Flexível do Banco de Dados do Azure para MySQL que você criou tem um banco de dados vazio chamado flexibleserverdb.

Está tendo algum problema? Queremos saber.

Configure uma regra de firewall para a sua instância de Servidor Flexível do Banco de Dados do Azure para MySQL

As instâncias de Servidor Flexível do Banco de Dados do Azure para MySQL são protegidas por padrão. Elas têm um firewall que não permite nenhuma conexão de entrada.

Você pode ignorar esta etapa se estiver usando o Bash porque o comando flexible-server create já detectou seu endereço IP local e o definiu no servidor MySQL.

Se você estiver se conectando à instância de Servidor Flexível do Banco de Dados do Azure para MySQL do Subsistema do Windows para Linux (WSL) em um computador Windows, precisará adicionar a ID do host WSL ao firewall. Obtenha o endereço IP do computador host executando o seguinte comando no WSL:

sudo cat /etc/resolv.conf

Copie o endereço IP após o termo nameserver e use 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, use o seguinte comando para abrir o firewall do servidor para seu aplicativo baseado em WSL:

az mysql flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --rule-name allowiprange \
    --output tsv

Configurar um banco de dados MySQL

Crie um banco de dados chamado demo usando o seguinte comando:

az mysql flexible-server db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --database-name demo \
    --server-name $AZ_DATABASE_NAME \
    --output tsv

Criar um usuário não administrador do MySQL e conceder permissão

Então crie um usuário não administrador e conceda a ele todas as permissões no banco de dados demo.

Observação

Você pode obter informações mais detalhadas sobre como criar usuários do MySQL em Criar usuários no Banco de Dados do Azure para MySQL.

Crie um script SQL chamado create_ad_user.sql para criar um usuário não administrador. Adicione o seguinte conteúdo e salve-o localmente:

export AZ_MYSQL_AD_NON_ADMIN_USERID=$(az ad signed-in-user show --query id --output tsv)

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 demo.* TO '$AZ_MYSQL_AD_NON_ADMIN_USERNAME'@'%';

FLUSH privileges;

EOF

Em seguida, use o seguinte comando para executar o script SQL, a fim de criar o usuário não administrador do Microsoft Entra:

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

Agora, use o seguinte comando para remover o arquivo de script SQL temporário:

rm create_ad_user.sql

Criar um projeto Java

Usando o seu IDE favorito, crie um projeto Java e adicione um arquivo pom.xml no diretório raiz:

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

Esse arquivo é um Apache Maven que configura seu projeto a ser usado:

  • Java 8
  • Um driver MySQL recente para Java

Preparar um arquivo de configuração para se conectar ao Banco de Dados do Azure para MySQL

Execute o seguinte script no diretório raiz do projeto para criar um arquivo 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_NAME}.mysql.database.azure.com:3306/demo?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}
EOF

Observação

Se você estiver usando a classe MysqlConnectionPoolDataSource como fonte de dados em seu aplicativo, remova "defaultAuthenticationPlugin=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin" da URL.

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

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

Observação

A propriedade de configuração url foi acrescentada a ?serverTimezone=UTC para instruir o driver JDBC a usar o formato de data UTC (Tempo Universal Coordenado) ao conectar-se ao banco de dados. Caso contrário, seu servidor Java não usaria o mesmo formato de data que o banco de dados, o que resultaria em um erro.

Criar um arquivo SQL para gerar o esquema de banco de dados

Você usará um arquivo src/main/resources/schema.sql para criar um esquema de banco de dados. Crie esse arquivo com o seguinte conteúdo:

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);

Codificar o aplicativo

Conectar-se ao banco de dados

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

Crie um arquivo src/main/java/DemoApplication.java e adicione o seguinte conteúdo:

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

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

Está tendo algum problema? Queremos saber.

Este código Java usará os arquivos database.properties e schema.sql que você criou anteriormente, para se conectar à instância do Servidor Flexível do Banco de Dados do Azure para MySQL e criar um esquema que armazenará seus dados.

Nesse arquivo, você pode ver que comentamos os métodos para inserir, ler, atualizar e excluir dados: você irá codificar esses métodos no restante deste artigo e poderá remover as marcas de comentários uma após a outra.

Observação

As credenciais de banco de dados são armazenadas nas propriedades user e password no arquivo database.properties. Essas credenciais são usadas durante a execução de DriverManager.getConnection(properties.getProperty("url"), properties);, pois o arquivo de propriedades é passado como um argumento.

Observação

A linha AbandonedConnectionCleanupThread.uncheckedShutdown(); no final é um comando específico do driver MySQL para destruir um thread interno ao desligar o aplicativo. Ele pode ser ignorado com segurança.

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

  • Usando o IDE, você deve clicar com o botão direito do mouse na classe DemoApplication e executá-la.
  • Usando o Maven, você pode executar o aplicativo por meio do: mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication".

O aplicativo deve se conectar à instância de Servidor Flexível do Banco de Dados do Azure para MySQL, criar um esquema de banco de dados e, em seguida, encerrar a conexão, como verá nos logs do console:

[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 classe Java Todo, ao lado da classe DemoApplication 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 +
                '}';
    }
}

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

Inserir dados no Banco de Dados do Azure para MySQL

No arquivo src/main/java/DemoApplication.java, após o método principal, adicione o seguinte método para inserir dados no banco 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 você pode remover a marca de comentário das seguintes duas linhas no método main:

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

A execução da classe principal deve produzir a seguinte saída:

[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

Como ler dados do Banco de Dados do Azure para MySQL

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

No arquivo src/main/java/DemoApplication.java, após o método insertData, adicione o seguinte método para ler dados do banco 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 você pode remover a marca de comentário da seguinte linha no método main:

todo = readData(connection);

A execução da classe principal deve produzir a seguinte saída:

[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

Está tendo algum problema? Queremos saber.

Atualizar dados no Servidor Flexível do Banco de Dados do Azure para MySQL

Então atualize os dados inseridos anteriormente.

Ainda no arquivo src/main/java/DemoApplication.java, após o método readData, adicione o seguinte método para atualizar os dados no banco 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 você pode remover a marca de comentário das seguintes duas linhas no método main:

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

A execução da classe principal deve produzir a seguinte saída:

[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

Excluir dados no Servidor Flexível do Banco de Dados do Azure para MySQL

Por fim, atualize os dados inseridos anteriormente.

Ainda no arquivo src/main/java/DemoApplication.java, após o método updateData, adicione o seguinte método para excluir os dados no banco 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 você pode remover a marca de comentário da seguinte linha no método main:

deleteData(todo, connection);

A execução da classe principal deve produzir a seguinte saída:

[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! Você criou um aplicativo Java que usa o JDBC para armazenar e recuperar dados do Servidor Flexível do Banco de Dados do Azure para MySQL.

Para limpar todos os recursos usados durante este guia de início rápido, exclua o grupo de recursos usando o seguinte comando:

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

Próximas etapas