Profe Macón
Programación Avanzada
2.º BT · Tecnologías de la Información
PM
Tienda de Cómics · Unidad de persistencia · Material 02

Nuestra primera conexión:
DriverManager y Connection

En el módulo anterior descubrimos por qué los productos desaparecían al cerrar la aplicación. Ahora veremos cómo Java solicita una conexión a MySQL, cómo interpreta la URL, qué ocurre si falla y cómo liberar los recursos correctamente.

CET3 · JDBCJava 17 + MavenMySQLSQLExceptionContinuidad con Controller y Service
1 · Recordamos

Ya sabemos por qué necesitamos una base de datos

En el material anterior comprobamos que la lista de productos no conserva los datos cuando cerramos nuestra aplicación. MySQL podrá almacenarlos, pero antes debemos conseguir que Java se comunique con su servidor.

Nuestra Tienda de Cómics
Java · objetos Producto · Controller · Service
↓
JDBC + driver MySQL
Medio de comunicación
↓
Servidor MySQL
Base de datos tiendacomics

En el módulo anterior aprendimos a distinguir JDBC, la API de Java para trabajar con bases de datos, del driver, la biblioteca específica que permite comunicarse con MySQL.

Nuevo problema: conocer la existencia de JDBC no significa que nuestra aplicación ya tenga una conexión. ¿Qué debemos indicar y qué instrucciones utilizaremos para conseguirla?
2 · Preparamos

¿Qué necesitamos antes de escribir el código?

Vamos a suponer que el servidor MySQL está instalado y funcionando en la misma computadora, que existe la base tiendacomics y que disponemos de un usuario con acceso. Si el servidor está en otro equipo, cambiaremos su dirección.

Servidor

Un servicio MySQL en funcionamiento, accesible por red.

Base de datos

Una base llamada tiendacomics. Todavía no necesitamos insertar productos.

Driver

MySQL Connector/J incluido como dependencia Maven de nuestro proyecto Java.

En un proyecto Maven, agregamos dentro de <dependencies> una dependencia como esta:

Fragmento del archivo pom.xml
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.4.0</version>
</dependency>

Maven descarga la biblioteca y la incorpora a las dependencias del proyecto. La versión indicada es un ejemplo compatible con Java 17; conviene utilizar la versión acordada para el entorno del curso.

Fíjate: no agregamos un paquete Java llamado java.sql mediante Maven. Ese paquete ya viene con Java. Lo que incorporamos es el driver específico de MySQL.
3 · Direccion

La URL JDBC: ¿a qué base queremos conectarnos?

El programa necesita una dirección para encontrar el servidor y la base de datos. En JDBC esa dirección se expresa mediante una URL de conexión.

Dirección de ejemplo
String url = "jdbc:mysql://localhost:3306/tiendacomics";
FragmentoSignificado
jdbc:mysql:Indica que queremos una conexión JDBC a MySQL.
localhostEl servidor se ejecuta en esta computadora.
3306Puerto habitual del servidor MySQL.
tiendacomicsNombre de la base de datos a utilizar.

La URL no contiene por sí sola todos los datos necesarios para autorizar la conexión. En nuestro primer ejemplo proporcionaremos también el nombre de usuario y la contraseña.

Para pensar: si la base de datos se llama comics2026, ¿qué parte de la URL cambiarías? ¿Y si MySQL estuviera en otra computadora?
4 · Drivermanager

DriverManager: la clase que solicita conexiones

Ya conocemos la dirección. Ahora necesitamos que Java obtenga una conexión utilizando el driver adecuado.

La API JDBC incluye una clase llamada DriverManager. Esta clase administra los drivers registrados y permite solicitar una conexión a partir de la URL y las credenciales.

La instrucción central
Connection conexion =
        DriverManager.getConnection(url, usuario, clave);

Leamos la instrucción de derecha a izquierda

DriverManager.getConnection(...)

Llama a un método estático. No necesitamos crear un objeto DriverManager. El método intenta obtener una conexión mediante un driver que reconozca la URL.

Connection conexion

Declara una variable llamada conexion, cuyo tipo es Connection. Si todo sale bien, recibe la referencia al objeto que representa la sesión de conexión.

Los argumentos url, usuario y clave son expresiones de tipo String.

No confundamos responsabilidades: DriverManager no guarda nuestros productos ni ejecuta una sentencia INSERT. Su trabajo aquí es conseguir una conexión; las operaciones SQL vendrán después.

¿Cómo sabe qué driver utilizar?

El driver de MySQL reconoce las URL que comienzan con jdbc:mysql:. Cuando la dependencia está bien incorporada, los drivers JDBC modernos suelen registrarse automáticamente; por eso normalmente no necesitamos escribir Class.forName("com.mysql.cj.jdbc.Driver"), frecuente en ejemplos antiguos.

5 · Connection

Connection: ¿qué recibimos al conectarnos?

El método getConnection() devuelve una referencia cuyo tipo es la interfaz java.sql.Connection.

Importaciones necesarias
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

Connection representa una sesión de comunicación con la base de datos. Por medio de ella podremos preparar instrucciones SQL, controlar transacciones y realizar otras operaciones JDBC.

La conexión es…

Un objeto de Java que representa nuestra comunicación con MySQL y permite acceder a operaciones JDBC.

≠

La conexión no es…

La propia base de datos, una tabla de productos ni una colección ArrayList.

Cuando dejamos de necesitar una conexión, debemos cerrarla correctamente para liberar recursos. El servidor MySQL puede atender varias conexiones, pero estas no son ilimitadas.

6 · Primera prueba

Primera prueba de conexión: un ejemplo mínimo

Vamos a reunir las instrucciones en un ejemplo pequeño. Por el momento no lo mezclaremos con ProductoService ni con los botones de la vista: solo queremos comprobar la comunicación.

Clase de prueba (las credenciales son ilustrativas)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class PruebaConexion {

    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/tiendacomics";
        String usuario = "usuario_prueba";
        String clave = "clave_prueba";

        try {
            Connection conexion =
                    DriverManager.getConnection(url, usuario, clave);

            System.out.println("Conexión establecida");
            conexion.close();

        } catch (SQLException e) {
            System.out.println("No fue posible conectarse");
            System.out.println(e.getMessage());
        }
    }
}

Recorramos la ejecución

  1. Se guardan los datos de acceso en tres variables.
  2. El programa llega al bloque try.
  3. DriverManager.getConnection(...) solicita la conexión al servidor.
  4. Si se obtiene, vemos el mensaje de éxito y llamamos a close().
  5. Si JDBC lanza una SQLException, se ejecuta el bloque catch.
Este es un ejemplo transitorio: si agregáramos más instrucciones dentro del try y una de ellas fallara antes de close(), podríamos dejar recursos abiertos. En la sección siguiente lo mejoraremos.
7 · Excepciones

SQLException: un error distinto a los del negocio

Ya estudiamos excepciones al separar las responsabilidades entre Controller y Service. Ahora recuperamos ese aprendizaje.

Formato

El usuario escribe “abc” en el campo de precio y falla la conversión numérica.

NumberFormatException

Regla del negocio

El producto tiene un precio negativo y el servicio rechaza el valor.

Excepción de validación

Persistencia

El servidor MySQL no responde o rechaza las credenciales.

SQLException

SQLException es una excepción comprobada (*checked exception*). Si un método utiliza una operación que puede lanzarla, debe manejarla mediante un try-catch o declarar con throws SQLException que puede propagarla.

Una declaración que veremos en la clase de conexión
public static Connection obtenerConexion() throws SQLException {
    return DriverManager.getConnection(url, usuario, clave);
}

La palabra throws no provoca una excepción; declara que el método puede comunicarla a quien lo invoque. Tampoco la resuelve por sí sola.

Esto resulta útil para separar responsabilidades: una clase dedicada a obtener conexiones no necesita mostrar un JOptionPane cuando MySQL falla. Puede propagar la excepción y dejar que otra capa determine cómo informar al usuario.

Relación con la unidad anterior: del mismo modo que distinguimos la validación del negocio de la respuesta visual al error, ahora distinguiremos el fallo de la base de datos de la forma de comunicarlo en la interfaz.
8 · Recursos

try-with-resources: una manera segura de cerrar

Una conexión ocupa recursos tanto en Java como en el sistema de base de datos. Conviene liberarlos aunque alguna instrucción falle.

Java dispone de una estructura llamada try-with-resources. Permite declarar recursos en el encabezado del try y cerrarlos automáticamente cuando termina ese bloque.

La misma prueba, ahora con cierre automático
try (Connection conexion =
        DriverManager.getConnection(url, usuario, clave)) {

    System.out.println("Conexión establecida");

} catch (SQLException e) {
    System.out.println("No fue posible conectarse");
    System.out.println(e.getMessage());
}

¿Qué cambió?

La variable conexion aparece dentro de los paréntesis del try. Cuando termina el bloque, Java invoca el cierre del recurso, incluso si se produce un error después de obtenerlo.

No tuvimos que escribir conexion.close() de forma explícita. La interfaz Connection admite este mecanismo porque implementa AutoCloseable.

Una precisión: cerrar conexiones evita fugas y uso innecesario de recursos. No resuelve por sí mismo los conflictos cuando dos usuarios modifican un mismo registro. Para esos casos existen transacciones y mecanismos de concurrencia de la base de datos.
9 · Organizacion

¿Dónde colocaremos esta configuración?

Imaginemos que dentro de unos días tenemos ProductoDAO, ClienteDAO y VentaDAO. Todos deberán conectarse con MySQL.

Problema conocido: ¿vamos a repetir la misma URL, usuario y contraseña dentro de cada una de esas clases? Ya sabemos qué dificultades provoca repartir una misma responsabilidad por todo el proyecto.

Vamos a crear, cuando pasemos a la práctica, una clase específica que proporcione conexiones. Podemos llamarla ConexionBD y ubicarla en el paquete config.

Esbozo de su responsabilidad; todavía no es la clase definitiva
public class ConexionBD {

    public static Connection obtenerConexion()
            throws SQLException {
        // Utilizar DriverManager con la configuración de MySQL.
    }
}

Su tarea será conocer los datos de conexión y entregar una Connection. No será responsable de validar precios, escuchar botones ni ejecutar todas las operaciones CRUD de productos.

Cuando estudiemos DAO, será cada DAO quien solicite conexiones para ejecutar su SQL. Así, la configuración se concentra en un lugar y las operaciones de acceso a datos se mantienen organizadas.

Seguridad: los usuarios y contraseñas usados en nuestros ejemplos son ficticios. En una aplicación real no debemos subir credenciales al repositorio. Más adelante podremos obtenerlas desde un archivo de configuración no versionado o variables de entorno.
10 · Comprobamos

Comprobamos lo que comprendimos

Responde estas preguntas y lee la devolución. Puedes regresar a las explicaciones cuando lo necesites.

1. ¿Qué función cumple DriverManager en nuestro ejemplo?

2. ¿Qué representa una variable del tipo Connection?

3. ¿Qué parte de jdbc:mysql://localhost:3306/tiendacomics indica el nombre de la base?

4. ¿Qué significa throws SQLException en la cabecera de un método?

5. ¿Por qué utilizamos try-with-resources con Connection?

11 · Cierre

Documentamos y preparamos el siguiente paso

Ya conocemos las piezas que necesitamos para solicitar una conexión. Todavía no hemos guardado ningún producto: eso será parte del trabajo con instrucciones SQL y DAO.

URL + credenciales → DriverManager → Connection → MySQL

Micro-entrega de documentación

Práctica por niveles: mínimo, interpretar la URL y la instrucción de conexión; estándar, explicar el recorrido y los posibles errores; desafío, adaptar el ejemplo para una base que está en otro servidor e investigar qué datos de conexión cambian.

Próximo material: desde una conexión activa, aprenderemos a preparar y ejecutar instrucciones SQL. Estudiaremos PreparedStatement, executeUpdate(), executeQuery() y ResultSet usando los productos de la tienda.

Material en curso
← Índice del curso