Introducción a Java JDBC
Qué es JDBC, cómo abstrae el acceso a bases de datos en Java y la arquitectura de la API JDBC.
JDBC (Java Database Connectivity) es la API estándar para comunicarse con una base de datos relacional desde Java. Reside en los paquetes java.sql y javax.sql y ofrece una forma neutral al proveedor para abrir una conexión, enviar SQL y leer resultados, ya sea que la base de datos sea PostgreSQL, MySQL, Oracle, SQL Server o un motor embebido como H2. Aprende la API una sola vez y solo cambia la URL de conexión al cambiar de base de datos.
La idea principal: una capa delgada y uniforme sobre muchas bases de datos
Tu código se escribe contra interfaces — Connection, Statement, ResultSet. Las clases concretas que las implementan se distribuyen en un JAR driver del proveedor. El trabajo de JDBC es mantener tu código en el lado de la interfaz de esa línea, de modo que cambiar de base de datos sea un cambio de configuración, no una reescritura.
Los tipos fundamentales
Un puñado de interfaces aparece en casi todos los programas JDBC:
| Interfaz | Rol |
|---|---|
DriverManager | Encuentra un driver para tu URL y devuelve una Connection |
Connection | Una sesión activa con la base de datos; la fábrica de sentencias |
Statement | Envía una cadena SQL fija |
PreparedStatement | Envía una plantilla SQL parametrizada (la opción segura por defecto) |
CallableStatement | Invoca un procedimiento almacenado |
ResultSet | Un cursor sobre las filas devueltas por una consulta |
SQLException | La excepción comprobada que puede lanzar cualquier llamada JDBC |
La estructura de todo programa JDBC
Casi todo acceso a datos sigue los mismos cinco pasos. A continuación se muestra contra una base de datos real, usando try-with-resources para que cada recurso se cierre solo:
String url = "jdbc:postgresql://localhost:5432/shop";
String sql = "SELECT id, name FROM product WHERE price < ?";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setBigDecimal(1, new BigDecimal("9.99"));
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getInt("id") + " " + rs.getString("name"));
}
}
}Es decir: (1) nombra una base de datos con una URL, (2) abre una Connection, (3) crea una sentencia, (4) ejecútala, (5) lee el ResultSet — luego cierra todo en orden inverso. El resto de esta parte amplía cada paso.
Un sistema de tipos neutral al proveedor
Las columnas SQL no son tipos Java. JDBC hace de puente entre ambos con las constantes java.sql.Types — VARCHAR, INTEGER, TIMESTAMP, entre otras — y un conjunto paralelo de métodos getXxx/setXxx. Raramente tendrás problemas con este mapeo, pero es la razón por la que una columna DATE va y viene como java.sql.Date y una NUMERIC como BigDecimal.
Un ejemplo práctico: la puerta de entrada, sin ningún driver instalado
Este programa no se conecta a nada — inspecciona la propia maquinaria JDBC. Le pregunta a DriverManager qué drivers están registrados, muestra el contrato exacto que obtienes cuando ninguno coincide con una URL, e imprime algunas de las constantes de tipo sobre las que está construida la API.
Lo que hay que extraer de la ejecución:
getConnectiones el único punto de entrada y está mediado porDriverManager. Nunca creas una conexión connew— nombras una base de datos con una URL y JDBC enruta la solicitud. El entorno de ejecución aquí no tiene ningún driver registrado, por lo que el recuento es0.- Cuando ningún driver reclama la URL, JDBC no devuelve
nullni se queda colgado — lanzaSQLExceptioncon el mensaje 'No suitable driver found'. Todo método JDBC señala los fallos de esta manera, razón por la queSQLExceptiones comprobada y debes manejarla en todas partes. - La excepción llevaba un SQLState (
08001, la clase estándar de 'el cliente no pudo establecer la conexión'). Los códigos SQLState son portables entre proveedores, a diferencia de los códigos de error enteros, que son específicos de cada proveedor. - Las constantes de
java.sql.Typesson simplesints (VARCHARes 12,INTEGERes 4). Son la forma en que la API nombra los tipos SQL independientemente de cualquier base de datos, y los pasarás asetNullyregisterOutParameteren capítulos posteriores. - Nada aquí necesitó una base de datos. La API JDBC es parte del JDK; solo el driver es externo. Esa separación es todo el diseño — tu código compila y razona sobre los tipos
java.sqlsin ninguna base de datos a la vista.
Cuándo recurrir a JDBC
JDBC es la base sobre la que se asienta toda herramienta de datos Java de nivel superior. Los mapeadores objeto-relacional como Hibernate o JPA, los constructores de consultas como jOOQ, y los ayudantes más ligeros como JdbcTemplate de Spring todos llaman a JDBC internamente. Recurre a JDBC directamente cuando quieras control total sobre el SQL, un mínimo de dependencias, o estés aprendiendo cómo funciona realmente la capa. Recurre a un ORM cuando prefieras mapear filas a objetos y omitir el código repetitivo. En cualquier caso, los conceptos de esta parte — conexiones, sentencias, conjuntos de resultados y transacciones — son lo que esas herramientas gestionan por ti.
Qué cubre el resto de esta parte
Cargar y elegir drivers, abrir y configurar una Connection, los tres tipos de sentencias (Statement, PreparedStatement y CallableStatement), y navegar por un ResultSet, además de transacciones, actualizaciones por lotes y lectura de metadatos de la base de datos. El siguiente capítulo comienza donde empieza toda conexión: el driver.