Herramientas de usuario

Herramientas del sitio


bloque4:bbdd

Conexión a bases de datos

La librería Java Database Connectivity (JDBC) es una API que proporciona acceso a bases de datos desde Java. Consta de dos paquetes:

java.sql 
javax.sql

Para poder trabajar con un sistema gestor de bases de datos determinado, necesitamos un controlador (Driver) que haga de intermediario entre la tecnología JDBC y la base de datos.

Por lo tanto, solo tenemos que descargar el controlador o driver concreto para dicha plataforma. A la hora de usar cualquier SGDB que use SQL las sentencias son siempre las mismas, solo cambia el driver de conexión.


Añadir el conector JDBC a nuestro proyecto

Para conectarnos con MySQL desde Java necesitamos el driver JDBC para MySql. Lo podemos descargar desde la web de Mysql. https://www.mysql.com/products/connector/

Debemos descargar el conector para JDBC (Java Database Connectivity). En la sección descargas indicaremos nuestro ssoo (platform independent) y descargaremos un fichero comprimido que contiene el fichero Jar del conector.

Para usar otro SGBD debemos buscar el driver conector en su soporte web. Una vez que lo tenemos descargado debemos añadirlo al classpath de nuestro proyecto. Para ello crearemos como siempre una carpeta (p.e. libs) y copiamos y pegamos dentro de ella el archivo Jar que acabamos de descargar.

Click derecho sobre nuestro proyecto en el explorador de proyectos de eclipse → Build Path → Configure Build Path. En la ventana que se abre seleccionamos Libraries y pulsamos sobre Add JARs. Y añadimos el fichero jar que está en nuestra carpeta libs.

Conexión con la Base de Datos MySQL

Siempre usaremos las clases del paquete java.sql.

Para realizar una conexión con la base de datos necesitamos:

  • Obtener una instancia de la Clase Connection. Representa la conexion con la base de datos.
  • La obtenemos a partir del método estático getConnection() de la clase DriverManager.

getConnection espera unas cadenas que indiquen todos los parámetros de conexión con la base de datos.

Connection conexionBD = null;
String servidor = "jdbc:mysql://localhost:3306/";
String bbdd = "reservas";
String user = "root";
String password = "";
conexionBD = DriverManager.getConnection(servidor + bbdd, user, password); 
  • user es el nombre de usuario de conexion a la base de datos MySql
  • password representa la contraseña, que estará en blanco si no la hemos definido en MySql.
  • servidor representa el tipo de driver, y el servidor-puerto al que nos queremos conectar.
  • bbdd representa la base de datos sobre la que queremos trabajar. Es un parámetro opcional.

A partir del objeto Connection obtenido, realizaremos todas las operaciones contra la base de datos.

Cerrar conexión

El método close() de la clase Connection, cierra la conexión con la base de datos.

conexionBD.close();

Conexión con otros SGBD

(p.e. PostgreSql, MariaDb) El proceso es el mismo, pero varía el tipo de servidor de bases de datos y también el driver (JAR) que debemos descargar del soporte oficial:

String servidor = "jdbc:postgresql://localhost:5432/";
String servidor = "jdbc:mariadb://localhost:3306/";

Consultas sobre la base de datos

Las operaciones CRUD responden a un acrónimo usado en bases de datos que hace referencia a las operaciones básicas (create, read, update, delete). En SQL todas las consultas se asocian a algún tipo de operación de las anteriores.

Podremos tratar las consultas desde un enfoque muy simple:

  • Consultas que no devuelven datos (INSERT, DELETE, UPDATE): llamadas también consultas de acción.
  • Consultas que devuelven datos (SELECT): llamadas también de selección, porque seleccionamos los datos a mostrar.

Preparación de consultas

Para preparar una consulta para su ejecución necesitamos usar la clase PreparedStatement. Su sintaxis de uso es bastante sencilla, ya que el método preparedStatement(String consulta) de la clase Connection nos devuelve un objeto de este tipo:

String consulta = "INSERT INTO usuarios(nombre, apellidos) VALUES ('Juan','Sola')";	
 
//A partir del objeto Connection obtenemos una consulta preparada
PreparedStatement sentencia = conexion.prepareStatement(consulta);
 
...
 
String consulta = "DELETE FROM usuarios WHERE nombre = 'Juan'";	
 
PreparedStatement sentencia = conexion.prepareStatement(consulta);

Ejecución de consultas

La clase PreparedStatement contiene principalmente 3 métodos de ejecución de consultas dependiendo del tipo de consulta a ejecutar:

  • Consultas de acción (INSERT, UPDATE, DELETE)

Usaremos el método executeUpdate(), que devuelve un int con el número de registros afectados. Ese valor podemos usarlo o no.

//Ejecuto la consulta
sentencia.executeUpdate();
 
//Ejecuto la consulta y obtengo el número de registros afectados (si lo necesitara)
int numeroRegistros = sentencia.executeUpdate();
  • Consultas de selección (SELECT, funciones, procedimientos que muestren datos)

Si la consulta devuelve registros, usaremos el método executeQuery(), que devuelve un tipo de datos ResultSet con el conjunto de registros obtenidos:

ResultSet resultado = sentencia.executeQuery();

Una vez que tenemos el objeto ResultSet con el conjunto de registros obtenidos, podemos recorrer el conjunto de registros ResultSet con un bucle while.

while(resultado.next()){
   System.out.println(resultado.getString(1) + ", " + resultado.getString(2));
}

De esta forma mostraríamos por pantalla las columnas 1 y 2 de cada registro obtenido. También podemos usar getXXX() si queremos obtener el tipo de datos concreto (p.e. getInt(1), getDouble(3), getDate(4)). Las columnas están numeradas empezando en el nº 1.

  • Ejecutar cualquier tipo de consulta

El método boolean execute() se usa cuando la consulta puede devolver ninguno, uno o varios conjuntos de registros ResultSet. Esto se hace para tener un mismo método que permite ejecutar cualquier consulta (acción o selección).

boolean estado = sentencia.execute();

Si el método devuelve true, quiere decir que el primer resultado obtenido es un ResultSet (Consulta Select). Podemos acceder a dicho conjunto de registros con el método getResultSet().

boolean estado = sentencia.execute();
//Si devuelve true es que he obtenido registros
if(estado){
   ResultSet resultado = sentencia.getResultSet();
   //procesamos el resultado
}

Si devuelve false indica que la consulta es del tipo (INSERT, UPDATE o DELETE), o que no ha devuelto resultados. Podemos acceder al número de registros afectados mediante el método getUpdateCount() que devuelve int.

Parametrizar una consulta

La clase PreparedStament almacena una consulta precompilada a la que podemos añadirle los valores de sus parámetros (caracter ?) posteriormente:

String consulta = "INSERT INTO productos(nombre, cantidad, precio) VALUES (?, ?, ?)"; 
PreparedStatement sentencia = conexion.prepareStatement(consulta);
 
//Despues de precompilar la consulta, damos valores a sus parámetros
sentencia.setString(1, "miel");    //La primera interrogación
sentencia.setInt(2, 57);           //La segunda
sentencia.setFloat(3, 4.34F);      //Y la tercera
 
//Finalmente ejecuto la consulta
sentencia.executeUpdate();

En la consulta SQL puedo indicar mediante el caracter ?, los parámetros a los que posteriormente voy a dar valor. La consulta : “INSERT INTO productos(nombre, cantidad, precio) VALUES (?, ?, ?)” tiene 3 parámetros.

Posteriormente mediante el objeto PreparedStatement puedo dar valor a esos parámetros indicando el tipo de valor, y el número de parámetro al que le doy el valor (1, 2 ó 3, ya que hay 3 interrogaciones).

Obtener el número de columnas de una consulta

Si en algún caso al realizar una consulta no sabemos cuántas columnas nos va a devolver, podemos usar el método getMetaData() que devuelve un objeto del tipo ResultSetMetaData.

Existen dos formas de usar dicho método. Se puede invocar desde un objeto de tipo ResultSet obtenido de la ejecución de una consulta:

ResultSet resultado = sentencia.executeQuery();
 
ResultSetMetaData resultadoMetaData = resultado.getMetaData();
int numeroColumnas = resultadoMetaData.getColumnCount();

También puedo obtenerlo antes de ejecutar la consulta llamando al método desde un objeto de tipo PreparedStatement:

PreparedStatement sentencia = conexión.preparedStatement(consulta);
 
ResultSetMetaData resultadoMetaData = sentencia.getMetaData();
int numeroColumnas = resultadoMetaData.getColumnCount();

Anexo: Ejemplos

Seleccionar datos

String sentenciaSql = "SELECT nombre, precio FROM productos";
PreparedStatement sentencia = null;
 
try {
  sentencia = conexion.prepareStatement(sentenciaSql);
  ResultSet resultado = sentencia.executeQuery();
 
  //Mostramos los datos
  while(resultado.next()){
     System.out.prinln(resultado.getStrig(1) + " - " + resultado.getString(2));
  }
 
} catch (SQLException sqle) {
  sqle.printStackTrace();
} finally {
  if (sentencia != null)
    try {
      //Debemos cerrar solo cuando hemos leido los datos.
      //Si cerramos antes de recorrer el ResultSet, perdemos los datos.
      sentencia.close();  
    } catch (SQLException sqle) {
      sqle.printStackTrace();
    }
}

Insertar datos

String sentenciaSql = "INSERT INTO productos (nombre, precio) VALUES (?, ?)";
PreparedStatement sentencia = null;
 
try {
  sentencia = conexion.prepareStatement(sentenciaSql);
  sentencia.setString(1, nombreProducto);
  sentencia.setFloat(2, precioProducto);
  sentencia.executeUpdate();
} catch (SQLException sqle) {
  sqle.printStackTrace();
} finally {
  //Nos aseguramos de cerrar los recursos abiertos
  if (sentencia != null)
    try {
      sentencia.close();
    } catch (SQLException sqle) {
      sqle.printStackTrace();
    }
}

Modificar datos

String sentenciaSql = "UPDATE productos SET nombre = ?, precio = ? " +
                      "WHERE nombre = ?";
PreparedStatement sentencia = null;
 
try {
  sentencia = conexion.prepareStatement(sentenciaSql);
  sentencia.setString(1, nuevoNombreProducto);
  sentencia.setFloat(2, precioProducto);
  sentencia.setString(3, nombreProducto);
  sentencia.executeUpdate();
} catch (SQLException sqle) {
  sqle.printStackTrace();
} finally {
  //Nos aseguramos de cerrar los recursos abiertos
  if (sentencia != null)
    try {
      sentencia.close();
    } catch (SQLException sqle) {
      sqle.printStackTrace();
    }
}

Eliminar datos

String sentenciaSql = "DELETE FROM productos WHERE nombre = ?";
PreparedStatement sentencia = null;
 
try {
  sentencia = conexion.prepareStatement(sentenciaSql);
  sentencia.setString(1, nombreProducto);
  sentencia.executeUpdate();
} catch (SQLException sqle) {
  sqle.printStackTrace();
} finally {
  //Nos aseguramos de cerrar los recursos abiertos
  if (sentencia != null)
    try {
      sentencia.close();
    } catch (SQLException sqle) {
      sqle.printStackTrace();
    }
}

© 2020 Fernando Valdeón

bloque4/bbdd.txt · Última modificación: 23/05/2019 11:16 por Fernando Valdeón