CRUD países

Vamos a realizar un CRUD de países para la base de datos Sakila

Tarea extra:

Añadir una opción 5.- Insertar varios

Que nos pregunte ¿Cuantos países quieres insertar?
Si le decimos, por ejemplo, 4, nos insertará en la tabla country lo siguiente:

Pais fake 1
Pais fake 2
Pais fake 3
Pais fake 4

CRUD actores con jdbc

package com.trifulcas.datos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;

public class MantenimientoActores {
	public static void main(String[] args) {

		try {

			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			System.out.println("Conexión correcta");

			Scanner in = new Scanner(System.in);
			int res = 0;
			do {
				System.out.println(
						"1.- Buscar actores\n2.- Añadir actores\n3.- Modificar actores\n4.- Eliminar\n0.- Salir");
				res = in.nextInt();
				String sql, nombre, apellido;
				int actor_id;
				PreparedStatement ps;
				switch (res) {
				case 1:
					System.out.println("Buscar actores");

					System.out.println("Dime una parte el apellido");
					String cad = in.next();
					sql = "select * from actor where last_name like ?";
					// Creo mi sentencia preparada. Tiene 1 parámetro
					ps = con.prepareStatement(sql);
					ps.setString(1, "%" + cad + "%");
					ResultSet rs = ps.executeQuery();
					while (rs.next()) {
						System.out.println(rs.getString("first_name") + " " + rs.getString("last_name"));
					}

					break;
				case 2:
					System.out.println("Añadir actores");
					System.out.println("Dime el nombre");
					nombre = in.next();
					System.out.println("Dime el apellido");
					apellido = in.next();

					sql = "insert into actor(first_name,last_name) values (?,?)";
					ps = con.prepareStatement(sql);
					ps.setString(1, nombre);
					ps.setString(2, apellido);
					if (ps.executeUpdate() == 1) {
						System.out.println("Registro insertado");
					} else {
						System.out.println("No se ha insertado el registro");
					}

					break;
				case 3:
					System.out.println("Modificar actores");
					System.out.println("Dime el id del actor que quieres modificar");
					actor_id = in.nextInt();
					System.out.println("Dime el nombre");
					nombre = in.next();
					System.out.println("Dime el apellido");
					apellido = in.next();

					sql = "update actor set first_name=?, last_name=? where actor_id=?";
					ps = con.prepareStatement(sql);
					ps.setString(1, nombre);
					ps.setString(2, apellido);
					ps.setInt(3, actor_id);
					if (ps.executeUpdate() == 1) {
						System.out.println("Registro modificado");
					} else {
						System.out.println("No se ha modificado el registro");
					}
					break;
				case 4:
					System.out.println("Eliminar actores");
					System.out.println("Dime el id del actor que quieres eliminar");
					actor_id = in.nextInt();
					sql = "delete from actor where actor_id=?";
					ps = con.prepareStatement(sql);
					ps.setInt(1, actor_id);
					if (ps.executeUpdate() == 1) {
						System.out.println("Registro eliminado");
					} else {
						System.out.println("No se ha eliminado el registro");
					}
					break;
				}
			} while (res != 0);

			con.close();

		} catch (Exception ex) {

			System.out.println(ex);
		}
	}
}

Prepared Statement

http://chuwiki.chuidiang.org/index.php?title=Ejemplo_con_preparedStatement

https://www.arquitecturajava.com/jdbc-prepared-statement-y-su-manejo/

http://puntocomnoesunlenguaje.blogspot.com/2017/11/java-jdbc-prepared-statements.html

Un ejemplo:

package com.trifulcas.datos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class AccesoSakila {

	public static void main(String[] args) {

		try {
			// Lo primero de todo crear una conexión CTRL+MAY+O -> importación automática de
			// los paquetes que falten

			// Esta línea nos 'registra' el conector mysql dentro de Java
			Class.forName("com.mysql.cj.jdbc.Driver");
			// Aquí nos creamos la conexión con una cadena de conexión
			// Lo primero es el tipo de conector: jdbc:mysql
			// Después la url del servidor SGBD //localhost:3306/
			// Después opcionalmente pero está bien ponerlo la base de datos /sakila
			// Por último usuario y contraseña root ''
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			System.out.println("Conexión correcta");

			// Statement es una sentencia SQL
			// PreparedStatement es una sentencia SQL lo único que 'preparada'

			String sql = "Select * from actor where last_name like '%b%'";
			System.out.println(sql);
			String cad = "b";

			sql = "select * from actor where last_name like '%" + cad + "%'";
			System.out.println(sql);

			// Cuando en mi sentencia tengo parámetros dinámicos que me pueden venir
			// de un teclado, o de un fichero o de un bucle o de donde sea
			// Yo puedo crear una sentencia preparada
			// Una sentencia sql en la que dejamos unos huecos para insertar un valor

			// En este insert yo estoy diciendo que voy a insertar un actor, pero no
			// especifico los valores
			// Estoy dejando dos huecos: los interrogantes
			sql = "insert into actor(first_name,last_name) values (?,?)";
			PreparedStatement ps = con.prepareStatement(sql);

			// Yo no puedo ejecutar mi sentencia preparada porque no he rellenado los huecos
			// Pero el conector ya ha establecido un 'plan' para mi sql

			// Para poder ejecutar la sentencia tengo que poner valores en los huecos
			ps.setString(1, "Juan");
			ps.setString(2, "L'hopital");
			// Aquí ejecuto la sentencia
			ps.executeUpdate();

			// Pongo otros valores en los huecos
			ps.setString(1, "Ana");
			ps.setString(2, "D'anjou");

			// ventajas: Más claridad que con la concatenación
			// Más rapidez porque se analiza el plan de ejecución una vez aunque se llame
			// varias
			// Evita inyección SQL
			// Evita problemas con comillas simples

			// Desventajas: Tenmos que indicar los parámetros y cuando son muchos podemos
			// liarnos
			ps.executeUpdate();

			
			// Podemos usarlo para modificar o en una condición para leer los datos
			ps = con.prepareStatement("select * from actor where first_name like ?");
			ps.setString(1, "%ar%");
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				System.out.println(
						rs.getInt("actor_id") + "  " + rs.getString("first_name") + "  " + rs.getString("last_name"));
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
	}

}

Ejercicio Sakila

Vamos a hacer un ejercicio muy sencillo de mantenimiento de actores. Un programa que nos va a mostrar el siguiente menú:

1.- Buscar actores
2.- Añadir actores
0.- Salir

En la primera opción nos va a pedir una cadena y nos va a mostrar los actores cuyo last_name contengan esa cadena (recordad que estamos en SQL: like).

En la segunda opción nos va a pedir un first_name y un last_name y nos va a añadir el actor a la base de datos.

Acceso a datos básico

package com.trifulcas.datos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class AccesoSakila {

	public static void main(String[] args) {

		try {
			// Lo primero de todo crear una conexión CTRL+MAY+O -> importación automática de los paquetes que falten

			// Esta línea nos 'registra' el conector mysql dentro de Java
			Class.forName("com.mysql.cj.jdbc.Driver");
			// Aquí nos creamos la conexión con una cadena de conexión
			// Lo primero es el tipo de conector: jdbc:mysql
			// Después la url del servidor SGBD //localhost:3306/
			// Después opcionalmente pero está bien ponerlo la base de datos /sakila
			// Por último usuario y contraseña root ''
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			System.out.println("Conexión correcta");
			
			// Con esta conexión yo puedo lanzar comandos a la base de datos.
			// Los comandos son SQL y pueden ser de dos tipos:
			// Lectura de datos (SELECT)
			// Modificación de datos (INSERT,UPDATE,DELETE)
			
			// Crear una sentencia Statement
			// Puedo lanzar dos tipos de ejecución: 
			// executeQuery: consulta, me devolverá datos
			// executeUpdate: modificación, no me devuelve datos
			Statement stmt = con.createStatement();
			
			// Crearme una sentencia sql para obtener unos datos
			String sql="select * from actor where first_name like 'b%'";
			
			// Guardo los resultados en un ResultSet: Una clase que nos permite ir leyendo los
			// Registros que nos ha devuelto nuestra consulta
			ResultSet rs = stmt.executeQuery(sql);
		
			// Cada vez que yo quiero un registro llamo a next()
			// Cuando no haya registros devuelve false y sale del while
			while (rs.next()) {
				// Una vez he 'cargado' un registro puedo acceder a los campos de dos maneras
				// Por el índice de la columna (empezando por el 1)
				System.out.println(rs.getInt(1) + "  " + rs.getString(2) + "  " + rs.getString(3));
				int id=rs.getInt(1);
				String first_name=rs.getString(2);
				String last_name=rs.getString(3);
				System.out.println(id+"-"+first_name+" - "+last_name);

				// Por el nombre de la columna
				// En los dos casos como Java es tipado tengo que usar el tipo correspondiente
				// getInt, getString,...
				id=rs.getInt("actor_id");
				first_name=rs.getString("first_name");
				last_name=rs.getString("last_name");
				System.out.println(id+" | "+first_name+" | "+last_name);
			}
			
			// Para modificar datos es más sencillo puesto que no tenemos resultados
			// Plantamos nuestra sentencia sql
			sql="insert into actor (first_name,last_name) values ('aa','bb')";
			
			// La ejecutamos con executeUpdate que no devuelve un ResultSet
			// Devuelve el número de filas afectadas
			int res=stmt.executeUpdate(sql);
			System.out.println(res);
			
			// La sentencia sql pueder un update o un delete
			sql="update actor set last_name='bbb' where first_name ='aa'";
			res=stmt.executeUpdate(sql);
			System.out.println(res);
			
		} catch (Exception ex) {
			System.out.println(ex);
		}
	}

}

Conexión base de datos

Para conectarnos desde java a las bases de datos tenemos varias opciones. Empezaremos con la más sencilla y en días sucesivos veremos otras más complejas.

En un proyecto Java podemos añadir el conector mysql. Primero lo tenemos que descargar, si queréis lo podéis hacer desde aquí:

https://github.com/juanpablofuentes/JavaNetmind/tree/main/MiPrimerProyecto/src

https://dev.mysql.com/downloads/connector/j/

Creamos un nuevo proyecto (para no mezclar) y añadimos este jar a las librerías de nuestro proyecto. Un manual:

https://www.knowprogram.com/jdbc/connect-mysql-database-eclipse/

Una vez lo tengamos añadido podemos conectarnos a nuestra base de datos con la cadena de conexión, de manera parecida a como lo hacemos en el workbench, indicando la url del servidor, la base de datos, y el usuario y la contraseña:

	Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");

A partir de aquí podemos acceder a la base de datos:


Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select * from actor");
			while (rs.next()) {
				System.out.println(rs.getInt(1) + "  " + rs.getString(2) + "  " + rs.getString(3));
			}
			rs = stmt.executeQuery("select * from actor");
			while (rs.next()) {
				System.out.println(
						rs.getInt("actor_id") + "  " + rs.getString("first_name") + "  " + rs.getString("last_name"));
			}

			int result=stmt.executeUpdate("insert into actor (first_name, last_name) values ('Eva','Pi')");  
			System.out.println(result+" filas afectadas");

			PreparedStatement ps = con.prepareStatement("select * from actor where first_name like ?");
			ps.setString(1, "%ar%");
			rs = ps.executeQuery();
			while (rs.next()) {
				System.out.println(
						rs.getInt("actor_id") + "  " + rs.getString("first_name") + "  " + rs.getString("last_name"));
			}

Manejo de excepciones

https://www.w3schools.com/java/java_try_catch.asp

https://beginnersbook.com/2013/04/try-catch-in-java/

https://www.geeksforgeeks.org/types-of-exception-in-java-with-examples/

https://www.geeksforgeeks.org/throw-throws-java/

public static void main(String[] args) {
		try {
			int a[] = new int[7];
			//a[14] = 30 ;
			a[4]=30/0;
			System.out.println("Sin errores");
		} catch (ArithmeticException e) {
			System.out.println("Error aritmético");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("Fuera de índices");
		} catch (Exception e) {
			System.out.println("Otra excepción");
		} finally{
			System.out.println("Bloque final");
		}
		System.out.println("Fuera del try");

	}
package com.trifulcas.excepciones;

import java.util.InputMismatchException;
import java.util.Scanner;

public class EjemplosExcepcion {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int[] foo = new int[3];
		boolean ok = false;
		do {
			try {
				ok = true;
				System.out.println("Introduce dividendo");
				int dividendo = in.nextInt();
				System.out.println("Introduce divisor");
				int divisor = in.nextInt();
				System.out.println("Introduce posicion");
				int posicion = in.nextInt();
				foo[posicion] = dividendo / divisor;
			} catch (ArithmeticException e) {
				ok = false;
				System.out.println("Error aritmético");
			} catch (ArrayIndexOutOfBoundsException e) {
				ok = false;
				System.out.println("Fuera de índices");
			} catch (InputMismatchException ex) {
				System.out.println("Quillo, mete un número porfi");
				ok = false;
				in.next(); // quitar la cadena de en medio
			} catch (Exception ex) {
				System.out.println(ex);
			}
		} while (!ok);
		System.out.println("Hola que tal");

	}

}

package com.trifulcas.testEjercito;

import java.util.Scanner;

import com.trifulcas.ejercitos.Ejercito;

public class Test {
	static Scanner in;

	public static void main(String[] args) {
		try {
			in = new Scanner(System.in);
			System.out.println("Bienvenido al simulador. Vamos a crear un ejército");
			System.out.println("¿Cuantos soldados quieres? (máximo 100)");
			int soldados = getNumero(100);
			System.out.println("¿Cuantos lanceros quieres?  (máximo 100)");
			int lanceros = getNumero(100);
			System.out.println("¿Cuantos capitanes quieres? (máximo 100)");
			int capitanes = getNumero(100);
			Ejercito miEjercito = new Ejercito(soldados, lanceros, capitanes);
			System.out.println("Ejercito creado con " + soldados + " soldados " + lanceros + " lanceros y " + capitanes
					+ " capitanes");
			System.out.println("El daño total es " + miEjercito.totalDanyo());
			int respuesta;
			do {
				respuesta = menu("¿Qué quieres hacer?\r\n" + "1- Atacar\r\n" + "2.- Retirada\r\n" + "0.- Salir");
				if (respuesta == 1) {
					atacar(miEjercito);
				} else if (respuesta == 2) {
					retroceder(miEjercito);
				} else if (respuesta != 0) {
					System.out.println("Los valores válidos son 1,2 y 0");
				}
			} while (respuesta != 0);
		} catch (Exception ex) {
			System.out.println("Error");
		}
	}

	public static int menu(String texto) {
		System.out.println(texto);
		int respuesta = getNumero(2);
		return respuesta;
	}

	public static void atacar(Ejercito miEjercito) {
		int respuesta;
		do {
			respuesta = menu(
					"Has decido atacar\r\n" + "1- Con todas las unidades\r\n" + "2.- Con una unidad\r\n" + "0.- Salir");

			if (respuesta == 1) {
				miEjercito.aLaCarga();
			} else if (respuesta == 2) {
				System.out.println("¿Con qué unidad quieres atacar (1-" + miEjercito.getTotalUnidades() + ") ?");
				int unidad = getNumero(miEjercito.getTotalUnidades());
				if (unidad >= 1 && unidad <= miEjercito.getTotalUnidades()) {
					miEjercito.getUnidad(unidad - 1).cargar();
				} else {
					System.out.println("Unidad fuera de rango");
				}
				// Otra manera: miEjercito.cargarUnidad(unidad);)
			} else if (respuesta != 0) {
				System.out.println("Los valores válidos son 1,2 y 0");
			}
		} while (respuesta != 0);
	}

	public static void retroceder(Ejercito miEjercito) {
		int respuesta;
		do {
			respuesta = menu("Has decido retroceder\r\n" + "1- Con todas las unidades\r\n" + "2.- Con una unidad\r\n"
					+ "0.- Salir");

			if (respuesta == 1) {
				miEjercito.retirada();
				;
			} else if (respuesta == 2) {
				System.out.println("¿Con qué unidad quieres retroceder (1-" + miEjercito.getTotalUnidades() + ") ?");
				int unidad = getNumero(miEjercito.getTotalUnidades());
				if (unidad >= 1 && unidad <= miEjercito.getTotalUnidades()) {
					miEjercito.getUnidad(unidad - 1).retroceder();
				} else {
					System.out.println("Unidad fuera de rango");
				}
			} else if (respuesta != 0) {
				System.out.println("Los valores válidos son 1,2 y 0");
			}
		} while (respuesta != 0);
	}

	public static int getNumero(int max) {
		boolean ok = true;
		int num = 0;
		do {
			try {
				ok = true;
				num = in.nextInt();
				if (num<0) {
					System.out.println("No valen números negativos");
					ok=false;
				}
				if (num>max) {
					System.out.println("No valen números mayores de "+max);
					ok=false;
				}
			} catch (Exception ex) {
				System.out.println("Debe introducir un número");
				in.nextLine();
				ok = false;
			}
		} while (!ok);
		return num;
	}
}

Ejercicio HashMap

En la clase cliente que hemos definido anteriormente vamos a añadir una propiedad ‘compras’ que es un hashmap de que nos indica el producto que ha comprado y la cantidad.

Vamos a añadir un método addCompra(String producto, int cantidad) que hará lo siguiente:

Si el producto no existe lo añade a compras
Si el producto ya está en compras suma la cantidad

Vamos a añadir un método eliminarProducto(String producto) que nos elimine el producto que le indiquemos

Vamos a añadir un método verProductos() que nos devuelva un ArrayList de String con los nombres de los productos.

Y un método totalUnidades() que nos devuelva el total de unidades que se han comprado.