1 of 46

UD8. Uso de BBDD

1

2 of 46

  1. Introducción

2

3 of 46

1. Introducción. Objetivos

  • Se han identificado las características y métodos de acceso a sistemas gestores de bases de datos.
  • Se han programado conexiones con bases de datos.
  • Se ha escrito código para almacenar información en bases de datos.
  • Se han creado programas para recuperar y mostrar información almacenada en bases de datos.
  • Se han efectuado borrados y modificaciones sobre la información almacenada.
  • Se han creado aplicaciones que muestren la información almacenada en bases de datos.
  • Se han creado aplicaciones para gestionar la información presente en bases de datos.

3

4 of 46

1. Introducción

Las aplicaciones informáticas suelen necesitar manejar grandes volúmenes de datos, para ello, las bases de datos relacionales son una opción común debido a su amplia adopción. Estas bases de datos organizan la información en tablas, donde cada fila representa un registro y cada columna un atributo. Es esencial tener una clave primaria para identificar de forma única cada registro.

El SGBD (Sistema Gestor de Bases de Datos) administra el almacenamiento, mantenimiento y recuperación de los datos.

JDBC (Java Database Connectivity) es una API en Java que simplifica el acceso a las bases de datos relacionales. Facilita la comunicación con diferentes motores de bases de datos mediante un único mecanismo, permitiendo la construcción de sentencias SQL dentro de aplicaciones Java de manera sencilla.

4

5 of 46

1. Introducción. JDBC

La API de JDBC, ubicada en el paquete java.sql, está compuesta por diversas clases que trabajan de manera conjunta. No es necesario conocer todas, pero es fundamental estar familiarizado con las principales:

  • DriverManager: permite manipular los diferentes controladores (drivers). Cada controlador proporciona acceso a un SGBD diferente.
  • Connection: establece una conexión entre la aplicación y la base de datos.
  • Statement: representa una sentencia SQL que será ejecutada por el servidor de la base de datos.
  • PreparedStatement: similar a Statement, pero permite configurar valores en la consulta, como la edad de un alumno o su fecha de nacimiento.
  • ResultSet: representa una tabla con los resultados generados por el SGBD luego de ejecutar una consulta de información (SELECT).

5

6 of 46

2. JDBC

6

7 of 46

2. JDBC. Driver

Cada fabricante de un SGBD desarrolla su producto utilizando mecanismos propios, como protocolos, llamadas y API de bajo nivel, para establecer una conexión con la base de datos y permitir el acceso a sus servicios. Sin embargo, las clases que forman parte de la API de JDBC no conocen estos detalles específicos de cada producto, como MySQL, Oracle Database o PostgreSQL.

Entre las clases de la API de JDBC, hay una clase especial llamada Driver, que es específica de cada SGBD. De hecho, cuando un fabricante desarrolla un nuevo SGBD, también desarrolla el driver correspondiente que permite su uso con JDBC. Este driver JDBC se añadirá a nuestro programa según el SGBD que hayamos elegido.

7

8 of 46

2. JDBC. Driver

De esta manera, el driver posibilita que cualquier aplicación Java, a través de la API JDBC, pueda aprovechar los servicios de cualquier SGBD para el cual exista un driver JDBC disponible. Esto elimina la necesidad de que cada aplicación Java tenga que comprender los detalles internos específicos de cada SGBD.

Agregar un driver a nuestro proyecto implica incluir la biblioteca que contiene la clase correspondiente al driver, es decir, seleccionar el fichero .jar que incluye el driver adecuado.

https://www.mysql.com/products/connector/

8

9 of 46

2. JDBC. Conexión

Antes de interactuar con la base de datos, es esencial establecer una conexión entre nuestra aplicación y el Sistema de Gestión de Base de Datos (SGBD). Esta conexión actúa como un conducto que facilita la comunicación entre ambas partes. Permite que las consultas SQL viajen desde la aplicación al SGBD y que los resultados de estas consultas se devuelvan en sentido contrario. Es importante mantener abierta esta conexión mientras sea necesaria. Una vez que ya no se requiera, es fundamental cerrarla. Si una conexión permanece abierta sin motivo, seguirá consumiendo recursos del SGBD.

Para establecer una conexión, podemos utilizar el método estático getConnection de DriverManager. Este método toma tres parámetros:

  • String url: identifica la base de datos a la que queremos acceder. Para MySQL, típicamente tiene la forma jdbc:mysql://<servidor>/<base_de_datos> donde:
    • <servidor>: Es el nombre o la dirección IP de la máquina donde está instalado el servidor de la base de datos. Si el servidor está en la máquina local, podemos usar localhost.
    • <base_de_datos>: Es el nombre de la base de datos dentro del SGBD.
  • String user: indica el usuario con el que nos conectaremos a la BD.
  • String password: la contraseña del usuario anterior.

El método devuelve un objeto de tipo Connection, que representa la conexión establecida entre nuestra aplicación y la base de datos.

9

10 of 46

2. JDBC. Conexión

Suponiendo que nuestra base de datos se llama "academia" y que tenemos un usuario llamado "Pepe" con la contraseña "12345", podemos establecer la conexión de la siguiente manera:

Cada conexión actúa como una tubería que permite el flujo de distintos objetos. Estos objetos representan información relevante tanto para el Sistema de Gestión de Base de Datos como para la aplicación.

10

11 of 46

2. JDBC. Conexión

El método getConnection() puede lanzar alguna de las siguientes excepciones si se produce algún error al crear la conexión:

  • SQLException: se produce si hay algún problema en el acceso a la base de datos o si la URL es nula.
  • SQLTimeoutException: ocurre cuando ha transcurrido un tiempo excesivo sin lograr establecer la conexión con la base de datos.

Cuando ya no necesitemos una conexión, es importante cerrarla utilizando el método close():

  • conexion.close();

Este método libera los recursos asociados con la conexión y la devuelve al pool de conexiones o la cierra definitivamente, dependiendo de la configuración y del tipo de conexión utilizada.

11

12 of 46

2. JDBC. Conexión

Crea un programa en Java que se conecte a tu servidor de MySQL utilizando el conector, ruta, base de datos, usuario y contraseña adecuado.

Si la conexión es satisfactoria se debe mostrar un mensaje por consola, si no es así, capturar una excepción SQLException que muestre el error.

12

13 of 46

2. JDBC. Ejecución de sentencias

Para ejecutar una sentencia SQL (SELECT, INSERT, UPDATE o DELETE), necesitaremos utilizar un objeto de la clase Statement. Al igual que con la conexión, estos objetos no se crean directamente mediante el operador new, sino a través de métodos que se encargan de construir, configurar y devolver los objetos necesarios.

La sintaxis simplificada de la sentencia SELECT es:

SELECT <lista_de_campos> *

FROM <tabla> <join>

[WHERE <condición>]

[ORDER BY <lista_de_campos>]

También podemos usar la sentencia SELECT para crear subconsultas, funciones de agregados o agrupamientos

La sintaxis básica de INSERT es:

INSERT INTO <tabla> [(<lista_de_campos>)]

VALUES (<valor1>, <valor2>, ...)

13

14 of 46

2. JDBC. Ejecución de sentencias

La sintaxis de UPDATE es:

UPDATE <tabla>

SET <campo1> = <valor1>,

<campo2> = <valor2>

[WHERE <condición>]

La sintaxis de DELETE es:

DELETE

FROM <tabla>

[WHERE <condición>]

Estas son las estructuras básicas de las sentencias SQL más comunes. Cada una puede variar en complejidad dependiendo de los requisitos específicos de la consulta.

14

15 of 46

2. JDBC. Ejecución de sentencias

Para comenzar, crearemos un objeto de tipo Statement de la siguiente manera:

Statement sentencia = conexion.createStatement();

Recuerda que el objeto conexion es de tipo Connection y representa la conexión establecida entre la aplicación y el SGBD.

Vamos a utilizar dos métodos para ejecutar sentencias SQL:

  • El primer método está reservado para las consultas (SELECT) que devuelven datos, los cuales son proporcionados por el SGBD.
  • El segundo método está destinado a las sentencias INSERT, UPDATE o DELETE, que no devuelven resultados.

15

16 of 46

2. JDBC. Ejecución de sentencias

El método executeQuery() de la clase Statement se utiliza para ejecutar una consulta y devuelve el resultado a través de un objeto de tipo ResultSet. Su prototipo es el siguiente:

ResultSet executeQuery(String sql)

Veamos un ejemplo de cómo consultar la tabla Alumnos:

String sql = "SELECT * FROM alumnos";

Statement sentencia = conexion.createStatement();

ResultSet rs = sentencia.executeQuery(sql);

Una vez obtenidos los resultados de la consulta, encapsulados en un objeto de tipo ResultSet, podemos proceder a trabajar con ellos. Al igual que la mayoría de las clases de la API de JDBC, el método executeQuery() puede lanzar dos excepciones en caso de que surja algún problema (SQLException y SQLTimeoutException).

16

17 of 46

2. JDBC. Ejecución de sentencias

La clase ResultSet funciona de manera similar a un iterador. Posee un cursor que apunta en cada momento a una única fila, conocida como fila activa. Este sistema permite acceder únicamente a los datos de la fila activa; para trabajar con todos los datos del objeto ResultSet, debemos desplazar el cursor de fila en fila.

Cuando se crea un objeto ResultSet, el cursor se posiciona inicialmente delante de la primera fila. Por lo tanto, es necesario avanzar el cursor por primera vez para situarlo en la primera fila y comenzar a trabajar con los datos de esta.

17

18 of 46

2. JDBC. Ejecución de sentencias

Para desplazarse de una fila a la siguiente en un ResultSet, se utiliza siguiente método:

  • boolean next(): este método mueve el cursor a la siguiente fila y devuelve verdadero o falso si ha sido posible realizar el movimiento. En otras palabras, devuelve false cuando el cursor ha recorrido todas las filas de datos y true en caso contrario.

El valor booleano que devuelve next() es crucial para determinar cuándo hemos terminado de procesar todas las filas de un ResultSet. Es común utilizar rs.next() como condición de un bucle while.

18

19 of 46

2. JDBC. Ejecución de sentencias

Ahora podemos extraer los datos de la fila activa. Para ello, disponemos de los siguientes métodos:

  • getString(String nombreCampo): devuelve el valor del campo especificado como una cadena.
  • getInt(String nombreCampo): devuelve el valor del campo especificado como un entero.
  • getDouble(String nombreCampo): devuelve el valor del campo especificado como un número de punto flotante de doble precisión.
  • getDate(String nombreCampo): devuelve el valor del campo especificado como una fecha.

Todos los métodos para extraer los datos de una tabla están sobrecargados para que, en lugar de especificar el nombre del campo, se pueda indicar su posición en la consulta. Es importante tener en cuenta que ResultSet enumera los campos de una consulta comenzando en 1.

  • getInt(int columnIndex): Devuelve el valor del campo en la posición de la columna especificada como un entero.

19

20 of 46

2. JDBC. Ejecución de sentencias

Crea un programa que muestre la información de todos los alumnos. Utiliza la base de datos academia.sql.

20

21 of 46

2. JDBC. Movimientos del cursor

El objeto ResultSet que hemos utilizado se puede denominar por defecto, ya que es de solo lectura (se pueden extraer los datos del objeto ResultSet, pero no modificarlos) y su cursor siempre avanza hacia delante. Sin embargo, es posible utilizar otros tipos de ResultSet que permiten la modificación de sus datos y mover el cursor hacia delante o atrás, así como posicionarlo en cualquier fila.

Para obtener otros tipos de ResultSet es necesario crear los objetos Statement mediante el método sobrecargado de Connection:

Statement createStatement(int tipoResultSet, int concurrencia);

El parámetro tipoResultSet admite cualquiera de las constantes:

  • ResultSet.TYPE_FORWARD_ONLY: indica que el cursor solo podrá moverse hacia delante.
  • ResultSet.TYPE_SCROLL_INSENSITIVE: el cursor podrá desplazarse hacia delante o atrás. Los datos contenidos en el ResultSet son una copia de los datos almacenados en la base de datos, por lo tanto, el ResultSet no es sensible a los posibles cambios que se produzcan en la base de datos.
  • ResultSet.TYPE_SCROLL_SENSITIVE: el cursor podrá desplazarse hacia delante o atrás. El ResultSet es sensible a los cambios que ocurran en la base de datos. Cualquier modificación de los datos que contiene el ResultSet en la base de datos produce una modificación en los datos del ResultSet. En este caso, el ResultSet actúa de una forma similar a una vista.

21

22 of 46

2. JDBC. Movimientos del cursor

El segundo parámetro indica la posibilidad de modificar los datos contenidos en el objeto ResultSet:

  • ResultSet.CONCUR_READ_ONLY: los datos contenidos en el ResultSet serán de solo lectura.
  • ResultSet.CONCUR_UPDATABLE: desde la aplicación es posible modificar los datos contenidos en el objeto ResultSet.

Cuando usamos el método createStatement() sin parámetros, los objetos ResultSet obtenidos por defecto serán de tipo TYPE_FORWARD_ONLY y CONCUR_READ_ONLY.

22

23 of 46

2. JDBC. Movimientos del cursor

Todos los métodos que mueven el cursor devuelven un booleano que indica si ha sido posible desplazar el cursor (true) o, por el contrario, el movimiento del cursor no puede realizarse (en este caso devuelven false). Un movimiento del cursor no podrá llevarse a cabo si la fila especificada no existe o el tipo de cursor no permite ese tipo de movimiento. Estos métodos son:

  • boolean next(): avanza el cursor y activa la siguiente fila.
  • boolean previous(): retrocede el cursor y activa la fila anterior.
  • boolean first(): coloca el cursor en la primera fila, activándola.
  • boolean last(): coloca el cursor en la última fila, activándola.
  • boolean absolute(int numeroFila): mueve el cursor a la enésima fila del ResultSet. El parámetro numeroFila especifica el número de fila al que hay que mover el cursor. Las filas se numeran comenzando en 1, es decir, la primera fila es la 1, la segunda la 2, etc. Existe otra forma de numerar las filas y consiste en utilizar números negativos, en este caso, la cuenta comienza por la última fila. La fila -1 es la última, la fila -2 es la penúltima, etcétera.
  • boolean relative(int cuantasFilas): mueve el cursor tomando como base su posición actual. El parámetro cuantasFilas especifica cuántas filas hay que desplazar el cursor. Si es positivo, el cursor avanza tantas filas como se especifique; y si es negativo, el cursor retrocede. Si el parámetro cuantasFilas es 0, el cursor no se moverá.
  • void beforeFirst(): coloca el cursor justo delante de la primera fila (posición inicial del cursor al crear un objeto ResultSet). Este método no tiene ningún efecto en un cursor vacío (sin ninguna fila).
  • void afterLast(): coloca el cursor justo después de la última fila. Esta posición del cursor es la misma que conseguimos tras recorrerlo mediante while (rs.next()). Este método no hace nada si el ResultSet está vacío.

23

24 of 46

2. JDBC. Movimientos del cursor

La capacidad de mover el cursor en un ResultSet puede llevarnos a perder la noción de su ubicación actual. Por esta razón, existen una serie de métodos que nos permiten verificar si el cursor se encuentra en posiciones específicas. Estos métodos nos hacen preguntas como: ¿Está el cursor en cierta posición? Todos estos métodos devuelven un valor booleano para indicar sí o no.

  • boolean isBeforeFirst(): este método especifica si el cursor se encuentra antes de la primera fila. Esta posición es la inicial cuando se crea un objeto ResultSet.
  • boolean isAfterLast(): indica si el cursor está colocado justo detrás de la última fila. Esta posición se alcanza después de recorrer el ResultSet usando while(rs.next()).
  • boolean isFirst(): devuelve true si el cursor apunta a la primera fila.
  • boolean isLast(): devuelve true si el cursor apunta a la última fila.

24

25 of 46

2. JDBC. INSERT, UPDATE, DELETE

En este caso, la ejecución de cualquiera de estas sentencias no devuelve un conjunto de datos como resultado, sino que simplemente realizan la operación indicada en el servidor. Para estas operaciones, disponemos del método executeUpdate(String sql), que ejecuta la sentencia SQL correspondiente y devuelve el número de filas que han sido afectadas por la operación. Es decir, el número de registros que se han eliminado, actualizado o insertado.

Aunque el nombre del método pueda llevar a confusión, es importante destacar que este método sirve tanto para insertar y actualizar como para eliminar registros en una tabla.

String sqlUpdate = "UPDATE alumnos SET nombre ='Pepico' WHERE dni LIKE '12345678A';

Statement sentenciaUpdate = conexion.createStatement();

System.out.println(sentenciaUpdate.executeUpdate(sqlUpdate));

25

26 of 46

2. JDBC. INSERT, UPDATE, DELETE

Inserta un alumno nuevo en la tabla “alumno”.

26

27 of 46

3. SQL Injection y sentencias parametrizadas

27

28 of 46

3. SQL Injection y sentencias parametrizadas

El SQL Injection es una técnica de hacking que Implica inyectar código SQL en una consulta a través de la entrada de datos. Supongamos que tenemos una aplicación que, en cierto momento, nos solicita el nombre de un alumno para eliminarlo. El código que podríamos utilizar se vería así:

String nombre;

nombre = new Scanner(System.in).next(); // pedimos el nombre al usuario

String sql = "DELETE FROM Alumnos WHERE nombre = '" + nombre + "'";

Si el usuario introduce el nombre "Perico Pérez", la consulta ejecutada en el servidor de la base de datos sería:

DELETE FROM Alumnos WHERE nombre = 'Perico Pérez'

Esto provocaría la eliminación del alumno con ese nombre. Sin embargo, si el usuario tiene conocimientos de SQL y introduce de manera malintencionada código SQL como si fuera el nombre del alumno, ese código se agregaría a la sentencia. Por ejemplo, si alguien quisiera eliminar completamente nuestra base de datos podría ingresar:

xxx' OR '1' = '1

La cadena ingresada por el usuario se combinaría con la nuestra, resultando en:

DELETE FROM Alumnos WHERE nombre = 'xxx' OR '1' = '1'

Como la cadena '1' siempre es igual a '1', esto causaría la eliminación de todos los registros de la tabla Alumnos.

28

29 of 46

3. SQL Injection y sentencias parametrizadas

El SQL Injection no se limita a la eliminación de datos, también puede inyectar código malicioso en otros contextos. Por ejemplo, en una consulta que muestre todos los alumnos de un curso:

String curso;

curso = new Scanner(System.in).nextLine(); // pedimos el curso al usuario

String sql = "SELECT * FROM Alumnos WHERE curso='" + curso + "'";

Si al solicitar el curso al usuario, este ingresa:

xxx ' ; DROP TABLE Alumnos; SELECT * FROM Alumnos WHERE curso= 'x

La cadena enviada al SGBD para su ejecución estará compuesta de tres sentencias, una de ellas será la eliminación completa de una tabla:

SELECT * FROM Alumnos WHERE curso = 'xxx'

DROP TABLE Alumnos

SELECT * FROM Alumnos WHERE curso = 'x '

Este tipo de ataque podría tener graves consecuencias, como la eliminación de la tabla Alumnos. Es importante tener cuidado con la entrada de datos y utilizar medidas de seguridad para prevenir el SQL Injection.

29

30 of 46

3. SQL Injection y sentencias parametrizadas

Como se ha visto, para evitar la inyección de SQL, no es recomendable construir sentencias mediante la concatenación de cadenas con datos proporcionados por el usuario. En su lugar, se deben utilizar sentencias parametrizadas, que son aquellas que contienen marcadores o parámetros que serán reemplazados por valores. Este enfoque permite adaptar y reutilizar la misma consulta varias veces. En JDBC, la interfaz PreparedStatement representa una consulta parametrizada.

Veamos el concepto de consulta parametrizada con un ejemplo: si deseamos consultar a todos los alumnos de un curso específico cuya nota media es superior a cierto valor de corte. La consulta parametrizada se formaría de la siguiente manera:

SELECT * FROM Alumnos WHERE curso = ? AND media > ?

En la consulta, se utiliza el símbolo de interrogación (?) para indicar la introducción de un parámetro. Si queremos que el curso sea "1A" y la nota de corte sea 6.0, podemos asignar estos valores a los parámetros:

El primer parámetro: ? = "1A". El segundo parámetro: ? = 6.0.

De esta forma, la consulta quedaría así:

SELECT * FROM Alumnos WHERE curso = '1A' AND media > 6.0

Este enfoque ayuda a prevenir la inyección de SQL y hace que las consultas sean más seguras y eficientes.

30

31 of 46

3. SQL Injection y sentencias parametrizadas

Una ventaja considerable de utilizar consultas con parámetros es que no es necesario preocuparse por las comillas, ya que solo hay que asignar valores a los parámetros y JDBC se encarga automáticamente de entrecomillar los campos según sea necesario. Además, si necesitas reutilizar la consulta, simplemente asignas nuevos valores a los parámetros.

Veamos el código necesario para utilizar consultas con parámetros:

// Consulta con parámetros. Cada parámetro se indica con ?

String sql = "SELECT nombre, media FROM Alumnos WHERE curso = ? AND media > ?";

// Creamos un objeto de tipo PreparedStatement

PreparedStatement sentencia = con.prepareStatement(sql);

// Asignamos los parámetros

sentencia.setString(1, curso); // El primer ? corresponde al curso

sentencia.setDouble(2, notaCorte); // El segundo ? corresponde a la nota de corte

ResultSet rs = sentencia.executeQuery(); // Ejecutamos la consulta

31

32 of 46

3. SQL Injection y sentencias parametrizadas

Para asignar los parámetros, disponemos de métodos como:

void setString(int indiceParametro, String valor)

void setInt(int indiceParametro, int valor)

void setDouble(int indiceParametro, double valor)

void setBoolean(int indiceParametro, boolean valor)

void setDate(int indiceParametro, Date valor)

En todos los métodos, el primer parámetro indica el índice del parámetro de la consulta (los parámetros se comienzan a contar desde 1), y el segundo parámetro es el valor que se asignará. Existen tantos métodos como tipos de datos, los mencionados aquí son solo algunos ejemplos.

32

33 of 46

3. SQL Injection y sentencias parametrizadas

Crea un programa que muestre todos los alumnos de una asignatura cuya nota es mayor que cierta nota de corte. El nombre de la asignatura y la nota serán introducidos por el usuario. Implementa un método para esta consulta, y repite tantas veces la consulta como veces quiera el usuario.

33

34 of 46

4. Operaciones CRUD

34

35 of 46

4. Operaciones CRUD

CRUD son las siglas en inglés de "Crear, Leer, Actualizar y Borrar", y se utilizan para referirse a las operaciones básicas que se realizan en una base de datos.

Hasta ahora, hemos estado trabajando con datos aislados, como simples variables. Esto nos ha permitido familiarizarnos con la API de JDBC y el manejo de una base de datos. Sin embargo, esta forma de trabajar no es la más común. A partir de ahora, trabajaremos con clases y objetos (como la clase Persona, la clase Mascota, etc.), a los cuales incorporaremos las operaciones CRUD, que se encargarán de gestionar el objeto en la base de datos.

Existe una técnica llamada mapeo objeto-relacional, que consiste en vincular cada atributo de una clase con un campo de una tabla en la base de datos. Es decir, convertimos los datos representados como objetos en registros de una tabla relacional, y viceversa.

35

36 of 46

4. Operaciones CRUD

A cada clase de nuestra aplicación se le añadirán los siguientes métodos:

  • create(): inserta los datos del objeto en la base de datos mediante una sentencia INSERT.
  • read(): mediante una sentencia SELECT, rescata los datos de la base de datos y los carga en un objeto.
  • update(): actualiza los datos de un objeto (que se habrán modificado) guardándolos en la base de datos, mediante una sentencia UPDATE.
  • delete(): elimina los datos del objeto actual de la base de datos.

Puedes ver un ejemplo para la clase Alumno aquí:

https://github.com/JMProf/Prog/blob/main/BBDD/Alumno.java

36

37 of 46

4. Operaciones CRUD

Crea la clase Profesor siguiendo la misma técnica CRUD.

37

38 of 46

4. Operaciones CRUD. Clases DAO

Desde una perspectiva de abstracción en la Programación Orientada a Objetos (POO), un enfoque purista argumentará que una clase debe encapsular sus características y comportamientos esenciales. Por ejemplo, en el caso de un alumno, la clase debería manejar sus datos personales, sus notas, sus matrículas, etc. Sin embargo, es ampliamente aceptado que las operaciones CRUD en una base de datos no son inherentes al mundo de un alumno.

Agregar métodos relacionados con operaciones de base de datos a una clase como Alumno puede considerarse una distorsión de la abstracción que intenta representar la realidad. Por esta razón, existe un enfoque en el que cada clase de interés en nuestra aplicación se diseña exclusivamente con base en la abstracción del mundo real. Si es necesario que esa clase se almacene en una base de datos, se diseña una segunda clase, llamada DAO (por sus siglas en inglés "Data Access Object"), con la única misión de realizar las operaciones CRUD en la base de datos para su clase correspondiente.

38

39 of 46

4. Operaciones CRUD. Clases DAO

Clase Alumno, que solo contiene atributos y métodos producto de la abstracción de los alumnos en la realidad; y clase AlunmoDAO, que está diseñada para interactuar con objeto de tipo Alumno con la BD. Cada clase DAO tendrá los mismos métodos, pero estará diseñada específicamente para una clase del modelo de dominio.

Puedes ver un ejemplo para la clase Alumno aquí:

https://github.com/JMProf/Prog/blob/main/BBDD/AlumnoDAO.java

39

40 of 46

5. Despliegue con Docker

40

41 of 46

5. Despliegue con Docker

Docker es una herramienta que permite empaquetar aplicaciones junto con todas sus dependencias (como bases de datos, librerías o configuraciones) en contenedores ligeros y portables. Esto garantiza que el programa se ejecute de la misma forma en cualquier entorno, sin necesidad de configuraciones complicadas o instalaciones adicionales.

Gracias a Docker, podemos desplegar nuestra aplicación Java y su base de datos MySQL de manera sencilla, pues no requiere que los usuarios instalen manualmente las dependencias de nuestro programa (como instalar el SGBD, crear usuarios, bases de datos…).

41

42 of 46

5. Despliegue con Docker

Realiza la siguiente práctica donde empaquetarás un sencillo programa Java que utilice una base de datos con MySQL:

https://jmprof.notion.site/Pr-ctica-de-Java-dockerizaci-n-de-una-app-Java-con-MySQL-1e0dc350e77b80639af3de3f1401c30b

42

43 of 46

6. SQLite

43

44 of 46

6. SQLite

SQLite es un SGBD que guarda las bases de datos en un fichero. Al contrario que MySQL, no es un SGBD de tipo cliente-servidor, por lo que el motor de SQLite no es un proceso independiente con el que se comunique nuestro programa Java.

En su página oficial se dice que es recomendable utilizar un SGBD tipo cliente-servidor en los siguientes casos:

  • Si los datos están separados de la aplicación por red.
  • Si hay alta concurrencia de escritura de datos.
  • Big Data.

Para el resto de casos, recomienda utilizar SQLite.

44

45 of 46

6. SQLite

Algunos ejemplos de uso son:

  • Aplicaciones embebidas en dispositivos (TV, consolas, cámaras, drones…).
  • Aplicaciones de escritorio.
  • Sitios web con “pocas” visitas (menos de 100.000 al día).
  • Análisis de datos.

Para utilizarlo con Java, será necesario utilizar la librería que contenga el conector para el JDBC, puedes encontrarlo en el siguiente enlace:

https://github.com/xerial/sqlite-jdbc/releases/tag/3.49.1.0

Para utilizarlo en tu programa Java, además de importar la librería, puedes utilizar la dirección jdbc:sqlite:miBaseDeDatos.db para el DriverManager.

45

46 of 46

6. SQLite

Descarga la base de datos libros.db disponible en el siguiente enlace, guárdala en la carpeta del proyecto y haz una consulta de la tabla “libros”.

https://github.com/nekrum/Ejercicios-SQLite/tree/master/bases_de_datos

46