Uso de Java y JDBC con Azure DB for MySQL: servidor flexible
SE APLICA A: Azure Database for MySQL: servidor flexible
En este tema se muestra cómo crear una aplicación de ejemplo que utiliza Java y JDBC para almacenar y recuperar información de Servidor flexible de Azure Database for MySQL.
JDBC es la API de Java estándar para conectarse a bases de datos relacionales tradicionales.
En este artículo, incluiremos dos métodos de autenticación: autenticación de Microsoft Entra y autenticación de MySQL. La pestaña Sin contraseña muestra la autenticación de Microsoft Entra y la pestaña Contraseña muestra la autenticación de MySQL.
La autenticación de Microsoft Entra es un mecanismo de conexión al servidor flexible de Azure Database for MySQL mediante identidades definidas en Microsoft Entra ID. Con la autenticación de Microsoft Entra, puede administrar las identidades de los usuarios de la base de datos y otros servicios de Microsoft en una ubicación central, lo que simplifica la administración de los permisos.
La autenticación de MySQL usa cuentas almacenadas en MySQL. Si decide usar contraseñas como credenciales para las cuentas, estas credenciales se almacenarán en la tabla user
. Dado que estas contraseñas se almacenan en MySQL, deberá administrar la rotación de las contraseñas por su cuenta.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar. Con una cuenta gratuita de Azure, ahora puede probar Azure Database for MySQL: servidor flexible de forma gratuita durante 12 meses. Para más información, consulte Probar el servidor flexible de Azure Database for MySQL de forma gratuita.
- Azure Cloud Shell o la CLI de Azure. Se recomienda Azure Cloud Shell, ya que se iniciará sesión automáticamente y tendrá acceso a todas las herramientas que necesite.
- Un kit de desarrollo de Java compatible, versión 8 (incluido en Azure Cloud Shell).
- La herramienta de compilación Apache Maven.
Preparación del entorno de trabajo
En primer lugar, use el siguiente comando para configurar algunas variables de entorno.
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)
Reemplace los marcadores de posición por los valores siguientes, que se usan a lo largo de este artículo:
<YOUR_DATABASE_NAME>
: nombre de la instancia de servidor flexible de Azure Database for MySQL, que debe ser única en Azure.<YOUR_AZURE_REGION>
: región de Azure que va a usar. Puede usareastus
de forma predeterminada, pero se recomienda que configure una región más cercana a la ubicación en la que vive. Puede ver la lista completa de las regiones disponibles; para ello, escribaaz account list-locations
.<YOUR_USER_ASSIGNED_MANAGED_IDENTITY_NAME>
: el nombre del servidor de identidad administrada asignado por el usuario, que debe ser único en Azure.
A continuación, cree un grupo de recursos:
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
Creación de una instancia de Azure Database for MySQL
Creación de una instancia de servidor flexible de Azure Database for MySQL y configuración de un usuario administrador
Lo primero que se crea es una instancia de servidor flexible de Azure Database for MySQL administrada.
Nota:
Puede leer información más detallada sobre la creación de servidores de MySQL en Creación de un servidor flexible de Azure Database for MySQL mediante Azure Portal.
Si usa la CLI de Azure, ejecute el siguiente comando para asegurarse de que tiene permisos suficientes:
az login --scope https://graph.microsoft.com/.default
Ejecute el siguiente comando para crear el servidor:
az mysql flexible-server create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_NAME \
--location $AZ_LOCATION \
--yes \
--output tsv
Ejecute el siguiente comando para crear una identidad asignada por el usuario para asignar:
az identity create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_USER_IDENTITY_NAME
Importante
Después de crear la identidad asignada por el usuario, pida a un usuario que tenga al menos el rol de administrador de roles con privilegios para conceder los siguientes permisos para esta identidad administrada asignada por el usuario: User.Read.All
, GroupMember.Read.All
y Application.Read.ALL
. Como alternativa, asigne a la identidad administrada asignada por el usuario el rol Lectores de directorio.. Para obtener más información, consulte la sección Permisos de autenticación de Active Directory.
Ejecute el siguiente comando para asignar la identidad al servidor flexible de Azure Database for MySQL para crear el administrador de Microsoft Entra:
az mysql flexible-server identity assign \
--resource-group $AZ_RESOURCE_GROUP \
--server-name $AZ_DATABASE_NAME \
--identity $AZ_USER_IDENTITY_NAME
Ahora ejecute el siguiente comando para establecer el usuario administrador de 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
Al establecer el administrador, se agrega un nuevo usuario a la instancia del servidor flexible de Azure Database for MySQL con permisos de administrador completos. Solo se puede crear un administrador de Microsoft Entra por instancia de servidor flexible de Azure Database for MySQL y la selección de otro sobrescribirá el administrador existente de Microsoft Entra configurado para el servidor.
Este comando crea una pequeña instancia de servidor flexible de Azure Database for MySQL y establece el administrador de Active Directory en el usuario que ha iniciado sesión.
La instancia de servidor flexible de Azure Database for MySQL que creó tiene una base de datos vacía denominada flexibleserverdb
.
¿Tiene algún problema? Cuéntenoslo.
Configuración de una regla de firewall para la instancia de servidor flexible de Azure Database for MySQL
Las instancias de servidor flexible de Azure Database for MySQL están protegidas de forma predeterminada. Tienen un firewall que no permite ninguna conexión entrante.
Puede omitir este paso si está usando Bash porque el comando flexible-server create
ya detectó su dirección IP local y la estableció en el servidor MySQL.
Si se conecta a la instancia de servidor flexible de Azure Database for MySQL desde el Subsistema de Windows para Linux (WSL) en un equipo Windows, deberá agregar el identificador de host de WSL al firewall. Para obtener la dirección IP de la máquina host, ejecute el siguiente comando en WSL:
sudo cat /etc/resolv.conf
Copie la dirección IP que sigue al término nameserver
y, a continuación, use el siguiente comando para establecer una variable de entorno para la dirección IP de WSL:
AZ_WSL_IP_ADDRESS=<the-copied-IP-address>
A continuación, use el siguiente comando para abrir el firewall del servidor en la aplicación basada en 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
Configuración de una base de datos MySQL
Cree una nueva base de datos llamada demo
con el comando siguiente:
az mysql flexible-server db create \
--resource-group $AZ_RESOURCE_GROUP \
--database-name demo \
--server-name $AZ_DATABASE_NAME \
--output tsv
Creación de un usuario que no sea administrador de MySQL y concesión de permisos
A continuación, cree un usuario que no sea administrador y concédale todos los permisos en la base de datos demo
.
Nota:
Puede leer información más detallada sobre cómo crear usuarios de MySQL en Creación de usuarios en Azure Database for MySQL.
Cree un script SQL denominado create_ad_user.sql para crear un usuario que no sea administrador. Agregue el siguiente contenido y guárdelo de forma local:
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
A continuación, use el siguiente comando para ejecutar el script SQL para crear el usuario que no es administrador de 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
Ahora use el siguiente comando para quitar el archivo de script SQL temporal:
rm create_ad_user.sql
Creación de un nuevo proyecto de Java
Con su IDE favorito, cree un nuevo proyecto de Java y agregue un archivo pom.xml en el directorio raíz:
<?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 archivo es un archivo de Apache Maven que configura el proyecto para usar:
- Java 8
- Un reciente controlador de MySQL para Java
Preparación de un archivo de configuración para conectarse a Azure Database for MySQL
Ejecute el siguiente script en el directorio raíz del proyecto para crear un archivo src/main/resources/application.properties y agregar detalles de configuración:
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
Nota
Si usa la clase MysqlConnectionPoolDataSource como origen de datos de la aplicación, quite "defaultAuthenticationPlugin=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin" de la dirección 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
Nota
La propiedad de configuración url
tiene anexado ?serverTimezone=UTC
para indicar al controlador de JDBC que use el formato de fecha UTC (hora universal coordinada) al conectarse a la base de datos. De lo contrario, el servidor Java no usaría el mismo formato de fecha que la base de datos, y daría lugar a un error.
Creación de un archivo SQL para generar el esquema de la base de datos
Usará un archivo src/main/resources/schema.sql para crear un esquema de base de datos. Cree ese archivo con el siguiente contenido:
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
Incorporación del código de la aplicación
Conectarse a la base de datos
A continuación, agregue el código Java que usará JDBC para almacenar y recuperar datos del servidor de MySQL.
Cree un archivo src/main/java/DemoApplication.java y agregue el contenido siguiente:
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();
}
}
¿Tiene algún problema? Cuéntenoslo.
Este código Java usará los archivos database.properties y schema.sql que creó anteriormente para conectarse al servidor flexible de Azure Database for MySQL y crear un esquema que almacenará sus datos.
En este archivo, puede ver que hemos comentado los métodos para insertar, leer, actualizar y eliminar datos: codificaremos esos métodos en el resto de este artículo y podrá quitar los comentarios uno tras otro.
Nota
Las credenciales de la base de datos se almacenan en las propiedades user y password del archivo database.properties. Estas credenciales se usan al ejecutar DriverManager.getConnection(properties.getProperty("url"), properties);
, ya que el archivo de propiedades se pasa como argumento.
Nota
La línea AbandonedConnectionCleanupThread.uncheckedShutdown();
del final es un comando específico del controlador de MySQL para destruir un subproceso interno al cerrar la aplicación.
Se puede omitir sin ningún problema.
Ahora puede ejecutar esta clase principal con su herramienta favorita:
- Con el IDE, debería poder hacer clic con el botón derecho en la clase DemoApplication y ejecutarla.
- Con Maven, puede ejecutar la aplicación mediante la ejecución de:
mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication"
.
La aplicación debería conectarse al servidor flexible de Azure Database for MySQL, crear un esquema de base de datos y, luego, cerrar la conexión, como debería ver en los registros de la consola:
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Closing database connection
Creación de una clase de dominio
Cree la nueva clase de Java Todo
, junto a la clase DemoApplication
y agregue el siguiente 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 clase es un modelo de dominio asignado a la tabla todo
que creó al ejecutar el script schema.sql.
Inserción de datos en Azure Database for MySQL
En el archivo src/main/java/DemoApplication.java, después del método main, agregue el método siguiente para insertar los datos en la base de datos:
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();
}
Ahora puede quitar la marca de comentario de las dos líneas siguientes en el método main
:
Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);
La ejecución de la clase main debería generar ahora la siguiente salida:
[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
Lectura de datos de Azure Database for MySQL
Después, lea los datos que se insertaron anteriormente para validar que el código funciona correctamente.
En el archivo src/main/java/DemoApplication.java, después del método insertData
, agregue el método siguiente para leer los datos de la base de datos:
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;
}
Ahora puede quitar la marca de comentario de la línea siguiente en el método main
:
todo = readData(connection);
La ejecución de la clase main debería generar ahora la siguiente salida:
[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
¿Tiene algún problema? Cuéntenoslo.
Actualización de datos en el servidor flexible de Azure Database for MySQL
A continuación, actualice los datos que se insertaron anteriormente.
En el archivo src/main/java/DemoApplication.java, después del método readData
, agregue el método siguiente para actualizar los datos de la base de datos:
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);
}
Ahora puede quitar la marca de comentario de las dos líneas siguientes en el método main
:
todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);
La ejecución de la clase main debería generar ahora la siguiente salida:
[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
Eliminación de datos en el servidor flexible de Azure Database for MySQL
Por último, elimine los datos que se insertaron anteriormente.
En el archivo src/main/java/DemoApplication.java, después del método updateData
, agregue el método siguiente para eliminar los datos de la base de datos:
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);
}
Ahora puede quitar la marca de comentario de la línea siguiente en el método main
:
deleteData(todo, connection);
La ejecución de la clase main debería generar ahora la siguiente salida:
[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
Limpieza de recursos
Felicidades. Ha creado una aplicación de Java que usa JDBC para almacenar y recuperar datos del servidor flexible de Azure Database for MySQL.
Para limpiar todos los recursos utilizados durante esta guía de inicio rápido, elimine el grupo de recursos con el siguiente comando:
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes