API JDBC
JDBC (Java Database Connectivity) está compuesto por un número determinado de clases e interfaces que permiten a cualquier programa escrito en Java acceder a una base de datos.
Este conjunto de clases reside en los paquetes: java.sql y javax.sql
javax.sql añade funciones de servidor como los RowSet, los pools de conexiones o las transacciones.
Para podernos conectar a la base de datos necesitamos un controlador o también conocido como Driver. Este driver no es más que la implementación del API JDBC para un gestor de Base de datos concreto Oracle, MySQL, Derby, …etc.

TIPOS DE CONTROLADORES
Los diferentes tipos de controladores que tenemos son:
- Puente JDBC-ODBC
- 100 % Java nativo
- 100 % Java / Protocolo independiente
- 100 % Java / Protocolo nativo

Proceso de obtención de resultados

IMPORTANTE: A partir de JDK 6, los drivers JDBC 4 ya se registran automáticamente y no es necesario el Class.forName(), sólo que estén en el classpath de la JVM.
ABRIR Y CERRAR CONEXIONES
Para poder acceder a una base de datos es necesario establecer una conexión.
Antes de conectarnos con la base de datos hay que registrar el controlador apropiado. Java utiliza la clase DriverManager para cargar inicialmente todos los controladores JDBC disponibles y que deseemos utilizar.
Para cargar un controlador se emplea del método forName() de la clase Class que devuelve un objeto Class asociado con la clase que se le pasa como parámetro.
La interfaz Connection es la que se encarga de la conexión con la base de datos. Mediante el método getConnection(), obtenemos un objeto de la clase Connection. Esta clase contiene todos los métodos que nos permiten manipular la base de datos.
|
1 |
Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/ejemplo", "ejemplo", "ejemplo"); |
Para cerrar la conexión utilizamos el método close() de la interfaz Connection.
|
1 |
conexion.close(); // Cerrar conexión |
CREAR CONSULTAS CON SQL
Para crear una consulta a la base de datos podemos utilizar 3 interfaces diferentes, cada uno tiene un uso especifico:
- Statement; Para ejecutar querys completas, es decir, tenemos todos los datos de la query.
- PreparedStatement; Para ejecutar querys parametrizadas. No tenemos todos los datos en este momento y utilizamos parámetros.
- CallableStatement; Para ejecutar querys a través de procedimientos almacenados definidos en la BBDD.
Statement
Para incluir una sentencia SQL utilizaremos la interfaz Statement, con el método createStatement() de la interfaz Connection.
Al crear una instancia del objeto Statement, podremos realizar sentencias SQL sobre la base de datos. Existen dos tipos de sentencias a realizar:
- Sentencias de modificación (update); Engloban a todos los comandos SQL que no devuelven ningún tipo de resultado como pueden ser los comandos INSERT, UPDATE, DELETE o CREATE.
- Sentencias de consulta (query); Son sentencias del tipo SELECT (sentencias de consulta) que retornan algún tipo de resultado.

Para las sentencias “update” la clase Statement el método siguiente que devolverá el número de filas afectadas por la sentencia SQL:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class InsertarDep { public static void main(String[] args) { //construir orden INSERT String sql = String.format("INSERT INTO departamentos ('nombre',...) VALUES ('Star Trek', '', ''....)"); Statement sentencia = conexion.createStatement(); int filas=0; filas = sentencia.executeUpdate(sql.toString()); sentencia.close(); // Cerrar Statement conexion.close(); // Cerrar conexión }// fin de main }// fin de la clase |
Para las sentencias “query” la clase Statement nos retorna el objeto Resulset con los datos solicitados, veamos un ejemplo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Statement sentencia = conexion.createStatement(); String sql = "SELECT * FROM departamentos"; ResultSet resul = sentencia.executeQuery(sql); // Recorremos el resultado para visualizar cada fila // Se hace un bucle mientras haya registros y se van visualizando while (resul.next()) { System.out.println(resul.getInt("id"), resul.getString("titulo"), resul.getString(3)); } resul.close(); // Cerrar ResultSet sentencia.close(); // Cerrar Statement |
El Objeto ResultSetcontrola la recuperación de da los registros.
- Respresentaun iterador
- Nos movemos con next() y previous()
- El cursos se coloca iniciatialmenteantes del primer registo.

Tenemos dos formas de acceder a las columnas.
Por posición:
resul.getInt(1), resul.getString(2), resul.getString(3), resul.getString(4), resul.getString(5)
Por nombre de la columna:
resul.getInt(“id”), resul.getString(“apellido”), resul.getString(“direccion”)….

Veamos un ejemplo de ejecución:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import java.sql.*; public class Main { public static void main(String[] args) { try { // Establecemos la conexion con la BD Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/ejemplo", "ejemplo", "ejemplo"); // Preparamos la consulta Statement sentencia = conexion.createStatement(); String sql = "SELECT * FROM departamentos"; ResultSet resul = sentencia.executeQuery(sql); // Recorremos el resultado para visualizar cada fila // Se hace un bucle mientras haya registros y se van visualizando while (resul.next()) { System.out.printf("%d, %s, %s %n", resul.getInt("id"), resul.getString("titulo"), resul.getString(3)); } resul.close(); // Cerrar ResultSet sentencia.close(); // Cerrar Statement conexion.close(); // Cerrar conexión } catch (ClassNotFoundException cn) { cn.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } }// fin de main }// fin de la clase |
En el código anterior vemos cómo realizar una consulta SELECT y procesar los datos.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import java.sql.*; public class InsertarEmple { public static void main(String[] args) { try { Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/ejemplo", "ejemplo", "ejemplo"); //construir orden INSERT String sql = "INSERT INTO empleados (emp_no, apellido, oficio,salario, dept_no) " + " VALUES (1001, 'nuevo', 'EMPLEADO', 2000, 10)"; System.out.println(sql); Statement sentencia = conexion.createStatement(); int filas=0; try { filas = sentencia.executeUpdate(sql.toString()); System.out.println("Filas afectadas: " + filas); } catch (SQLException e) { //e.printStackTrace(); System.out.printf("HA OCURRIDO UNA EXCEPCIÓN:%n"); System.out.printf("Mensaje : %s %n", e.getMessage()); System.out.printf("SQL estado: %s %n", e.getSQLState()); System.out.printf("Cód error : %s %n", e.getErrorCode()); } sentencia.close(); // Cerrar Statement conexion.close(); // Cerrar conexión } catch (ClassNotFoundException cn) { cn.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } }// fin de main }// fin de la clase |
En el código anterior vemos cómo realizar una inserción.
PreparedStatement
Define métodos para trabajar con instrucciones SQL pre compiladas, que son más eficientes.
También se usan para poder utilizar instrucciones SQL parametrizadas. Para establecer parámetros en una instrucción SQL basta con sustituir el dato por un signo de interrogación. (Select * from Tabla where Nombre=?).
El parámetro se sustituye por el valor mediante el método setXXX(int lugar, XXX Valor).
|
1 2 3 4 5 6 7 8 9 |
String sql = "INSERT INTO departamentos VALUES " + "( ?, ?, ? )"; System.out.println(sql); PreparedStatement sentencia = conexion.prepareStatement(sql); sentencia.setInt(1, Integer.parseInt(dep)); sentencia.setString(2, dnombre); sentencia.setString(3, loc); |
PreparedStatement no utiliza los métodos de Statement para ejecutar las querys, en su lugar, se pasa la query en el propio constructor.
Igual que antes podemos ejecutar dos tipos de consultas query y update.
Ejemplo Inserción:
|
1 2 3 4 5 6 7 8 9 |
PreparedStatement ps = con.prepareStatement( "INSERT INTO misiones(nombre, nave, descripcion) VALUES (?, ?, ?)"); ps.setString(1, m.getNombre()); ps.setInt(2, m.getNave()); ps.setString(3, m.getDescripcion()); ps.executeUpdate(); ps.close(); |
Ejemplo Select:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
PreparedStatement ps = con.prepareStatement("SELECT * FROM misiones"); ResultSet rs = ps.executeQuery(); List<Misiones> result = null; while (rs.next()) { if (result == null) result = new ArrayList<>(); result.add(new Misiones(rs.getInt("id"), rs.getString("nombre"), rs.getInt("nave"), rs.getString("descripcion"))); } rs.close(); ps.close(); |
Ejemplo Select con Filtro:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
PreparedStatement ps = con.prepareStatement("SELECT * FROM misiones WHERE id = ?"); ps.setInt(1, id); ResultSet rs = ps.executeQuery(); Misiones result = null; if (rs.next()) { result = new Misiones(rs.getInt("id"), rs.getString("nombre"), rs.getInt("nave"), rs.getString("descripcion")); } rs.close(); ps.close(); |
Ejemplo Update:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public void update(Misiones m) throws SQLException { if (m.getId() == 0) return; PreparedStatement ps = con.prepareStatement( "UPDATE misiones SET nombre = ?, nave = ?, descripcion = ? WHERE id = ?"); ps.setString(1, m.getNombre()); ps.setInt(2, m.getNave()); ps.setString(3, m.getDescripcion()); ps.setInt(4, m.getId()); ps.executeUpdate(); ps.close(); } |
Ejemplo delete
|
1 2 3 4 5 6 7 8 9 10 11 12 |
public void delete(int id) throws SQLException { if (id <= 0) return; PreparedStatement ps = con.prepareStatement("DELETE FROM misiones WHERE id = ?"); ps.setInt(1, id); ps.executeUpdate(); ps.close(); } |
Metadatos
Los metadatos se pueden considerar como información adicional a los datos que almacena la tabla.
Se utiliza un objeto ResultSetMetaData para recoger los metadatos de una consulta. Dicho objeto expone los siguientes métodos:
- getColumnName(); devuelve el nombre de la columna.
- getColumnCount(); nos indica el numero de columnas de la consulta.
- getTableName(); devuelve el nombre de la tabla.
- getColumnType(); nos dice el tipo de datos de la columna.
- isReadOnly(); especifica si los datos son de solo lectura.
Ejemplo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
Connection conexion = DriverManager.getConnection( "jdbc:mysql://localhost/ejemplo", "ejemplo", "ejemplo"); Statement sentencia = conexion.createStatement(); ResultSet rs = sentencia .executeQuery("SELECT * FROM departamentos"); ResultSetMetaData rsmd = rs.getMetaData(); int nColumnas = rsmd.getColumnCount(); String nula; System.out.printf("Número de columnas recuperadas: %d%n", nColumnas); for (int i = 1; i <= nColumnas; i++) { System.out.printf("Columna %d: %n ", i); System.out.printf(" Nombre: %s %n Tipo: %s %n ", rsmd.getColumnName(i), rsmd.getColumnTypeName(i)); if (rsmd.isNullable(i) == 0) nula = "NO"; else nula = "SI"; System.out.printf(" Puede ser nula?: %s %n ", nula); System.out.printf(" Máximo ancho de la columna: %d %n", rsmd.getColumnDisplaySize(i)); }// for sentencia.close(); rs.close(); conexion.close(); } catch (ClassNotFoundException cn) { cn.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } }// fin de main } |