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);
		}
	}

}

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;
	}
}

Ejercicios colecciones

Vamos a crear una clase ‘Cliente’ que tendrá las siguientes propiedades:

String nombre
String email

Que se deben pasar en el constructor. Son privadas con getters y setters.

Vamos a añadir una propiedad ‘telefonos’ que es un arrayList de tipo String.

Tendremos un método ‘addTelefono’ que nos añade el teléfono al arraylist SI NO ESTÁ YA introducido

Tendremos un método ‘getTelefono’ al que le pasamos un índice y nos devuelve el teléfono que está en ese índice. Si no hay teléfonos en ese índice devuelve la cadena vacía.

Por último vamos a tener un método buscarTelefono al que le pasamos una cadena y nos devuelve un ArrayList con todos los teléfonos que contengan esa cadena. Si no hay ninguno, devuelve un ArrayList vacío. Ejemplo, si mis teléfonos son: [‘669669669′,’634634634′,’669789967’] y busco ‘669’ me devuelve [‘669669669′,’669789967’]

Un ejemplo inspirador:

package com.trifulcas.ejemplos;

import java.util.ArrayList;
import java.util.List;

public class Alumno {
	private String nombre;
	private int nota;
	private List<Integer> notas;
	
	
 	public Alumno(String nombre, int nota) {
		super();
		this.nombre = nombre;
		this.nota = nota;
		notas=new ArrayList<Integer>();
	}
	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}
	/**
	 * @param nombre the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	/**
	 * @return the nota
	 */
	public int getNota() {
		return nota;
	}
	/**
	 * @param nota the nota to set
	 */
	public void setNota(int nota) {
		this.nota = nota;
	}
	
	public String toString() {
		return nombre+"|"+nota;
	}
	public void addNota(int nota) {
		notas.add(nota);
	}
	public int getFromNotas(int index) {
		return notas.get(index);
	}
}

Resumen colecciones


public class ResumenColecciones {

	public static void main(String[] args) {
		//Las colecciones nos sirven para almacenar valores de forma dinámica
		// A diferencia de un array el tamaño no está definido de antemano
		// Hay muchos tipos de colecciones que se engloban en tres tipos:
		// List, Map y Set
		// List->Lista de objetos
		// Set ->Lista de objetos sin duplicados
		// Map-> Lista de pares clave,valor
		
		// Ejemplo de List: ArrayList
		// Lo definimos por el interfaz List
		List<String> productos=new ArrayList<String>();
		
		// Añadimos con add, elminamos con remove
		
		productos.add("Manzana");
		productos.add("Pera");
		productos.add("Melocotón");
		System.out.println(productos);
		productos.remove("Pera");
		System.out.println(productos);
		
		// Lo recorremos con for each
		for(String el:productos) {
			System.out.println(el);
		}
		
		// Lo cambiamos con set
		productos.set(0, "MAnzana Golden");
		System.out.println(productos);
		
		// Utilidades como contains, indexOf
		// Las utilidades de Collections: sort, shuflle, search...
		
		System.out.println(productos.contains("Melocotón"));
		
		// Puede ser de cualquier tipo
		List<Integer> foo1=new ArrayList<Integer>();
		List<Boolean> foo2=new ArrayList<Boolean>();
		List<Alumno> foo4=new ArrayList<Alumno>();
		List<Infanteria> foo3=new ArrayList<Infanteria>();
		List<LocalDate> foo5=new ArrayList<LocalDate>();
		
		// Para pares clave, valor tenemos HashMap
		// Que se implementa mediante su interfaz 'Map'
		
		Map<String,String> referencias=new HashMap<String,String>();
		
		// Se añaden elementos con el put
		referencias.put("QW23", "Tornillo fino 0.2mm");
		referencias.put("QW24", "Tornillo fino 0.4mm");
		referencias.put("QW25", "Tornillo fino 0.8mm");
		
		// Se eliminan con remove
		referencias.remove("QW24");
		
		// Se recorren por valores con foreach
		for(String el:referencias.values()) {
			System.out.println(el);
		}
		
		// Se recorren con clave y valor con EntrySet
		for(Map.Entry<String, String> el:referencias.entrySet()) {
			System.out.println(el.getKey()+" "+el.getValue());
		}
		
		// El tamaño tanto de ArrayList como HashMap está en size
		System.out.println(referencias.size());
		
		// Pueden ser usados como parámetros en funciones
		// Como propiedades en clases
		// Como valores de retorno en funciones
		
		Alumno pep=new Alumno("Pep",4);
		pep.addNota(8);
		System.out.println(pep.getFromNotas(0));
	}

}

Ejemplo HashMap


	public static void main(String[] args) {

		// Me creo un map con alumnos
		Map<String, Alumno> alumnos = new HashMap<String, Alumno>();
		alumnos.put("Ana", new Alumno("Ana Pi", 7));
		alumnos.put("Eva", new Alumno("Eva González", 8));
		alumnos.put("Pep", new Alumno("José Bou", 6));
		alumnos.put("Rosa", new Alumno("Rosa", 3));
		alumnos.put("Juan", new Alumno("Juan", 4));

		System.out.println(mejorAlumno(alumnos));
		System.out.println(aprobados(alumnos));
	}

	// Paso como parámetro un hashmap y devuelvo un resultadop
	public static Alumno mejorAlumno(Map<String, Alumno> alumnos) {
		Alumno res = null;
		for (Alumno alumno : alumnos.values()) {
			if (res == null || alumno.getNota() > res.getNota()) {
				res = alumno;
			}
		}
		return res;
	}

	// Paso como parámetro un hashmap y devuelvo otro hashmap
	// Filtrando los aprobados
	public static Map<String, Alumno> aprobados(Map<String, Alumno> alumnos) {
		Map<String, Alumno> res = new HashMap<String, Alumno>();
		// Recorrer el mapa en un par clave valor y filtrar los alumnos
		for (Map.Entry<String, Alumno> alumno : alumnos.entrySet()) {
			if (alumno.getValue().getNota() >= 5) {
				res.put(alumno.getKey(), alumno.getValue());
			}
		}
		return res;
	}

HashMap

https://www.javatpoint.com/java-hashmap

https://guru99.es/working-with-hashmaps/

https://www.geeksforgeeks.org/java-util-hashmap-in-java-with-examples/

https://www.baeldung.com/java-hashmap

public static void main(String[] args) {
		
		// Especificar los tipos de los dos cmapos, la clave y el valor
		// Defino por la intefaz 'Map' y no pr HashMap
		Map<Integer, String> map = new HashMap<Integer, String>();// Creating HashMap
		// Otra manera
		HashMap<Integer, String> mapita = new HashMap<Integer, String>();// Creating HashMap
		
		// Los valores se añaden con 'put'
		// En formato clave, valor
		map.put(1, "Eva"); // Put elements in Map
		map.put(2, "Juan");
		map.put(3, "Ana");
		map.put(4, "Pep"); //{1=Eva, 2=Juan, 3=Ana, 4=Rosa}

		System.out.println(map);
		
		// Recorrer un HashMap
		for (Map.Entry<Integer, String> m : map.entrySet()) {
			System.out.println(m.getKey() + " " + m.getValue());
		}
		
		// Añado un valor que ya existe	
		// Lo sustituye
		map.put(4, "Rosa");
		
		for (Map.Entry<Integer, String> m : map.entrySet()) {
			System.out.println(m.getKey() + " " + m.getValue());
		}
		
		// Función especial para añadir sólo si no existe
		map.putIfAbsent(4, "Pepe");
		System.out.println(map);
		map.putIfAbsent(5, "Pepe");
		System.out.println(map);
		
		// Nos elimina el elemento con la clave '2'
		map.remove(2);
		System.out.println(map);
		
		// Aquí la clave es una cadena y el valor es de tipo alumno
		Map<String,Alumno> mapa=new HashMap<String,Alumno>();
		Map<Alumno,String> mapaalreves=new HashMap<Alumno,String>();
		
		// Los añado creando alumnos al vuelo
		mapa.put("Ana", new Alumno("Ana Pi",7));
		mapa.put("Eva", new Alumno("Eva González",8));
		mapa.put("Pep", new Alumno("José Bou",6));
		
		// Obtener un valor concreto de una clave
		System.out.println(mapa.get("Ana"));
		
		System.out.println(mapa);
		for (Map.Entry<String, Alumno> m : mapa.entrySet()) {
			System.out.println(m.getKey() + " " + m.getValue().getNombre());
		}
		
		// Elimino por la clave
		mapa.remove("Ana");
		// Recorrer por valores, porque no me interesa la clave
		for(Alumno al:mapa.values()) {
			System.out.println(al);
		}
		
		// Muestra las claves de mi HashMap
		for(String key:mapa.keySet()) {
			System.out.println(key);
		}
	}

Ejemplos ArrayList

public static void main(String[] args) {
		List<String> alumnos=new ArrayList<String>();

		alumnos.add("Eva");
		alumnos.add("");
		alumnos.add("María");
		alumnos.add("Rosa");
		
		Collections.addAll(alumnos, "juan","","Pep");
		
		System.out.println(alumnos);
		
		List<String> alumnosTrim=arrayTrim(alumnos);
		
		System.out.println(alumnosTrim);
		Collections.shuffle(alumnosTrim);
		System.out.println(alumnosTrim);
		Collections.sort(alumnosTrim);
		System.out.println(alumnosTrim);
	}

	// Tanto lo que devuelvo como el parámetro es de tipo List
	public static List<String> arrayTrim(List<String> lista){
		List<String> res=new ArrayList<String>();
		for(String el:lista) {
			if (el!="") {
				res.add(el);
			}
		}
		return res;
	}

Otro ejemplo:

	public static void main(String[] args) {
		// ArrayList de Alumnos, es decir de una clase propia
		List<Alumno> alumnos=new ArrayList<Alumno>();

		// Añadir creandolos al vuelo
		alumnos.add(new Alumno("Eva",6));
		alumnos.add(new Alumno("Rosa",7));
		alumnos.add(new Alumno("Pep",3));
		alumnos.add(new Alumno("Ana",4));
		
		// Añadir creando una variable y añadiendo esa variable
		Alumno foo=new Alumno("Rosa",8);
		alumnos.add(foo);
		
		// Si he sobreescrito el toString lo puedo ver todo con un
		// simple print
		System.out.println(alumnos);
		List<Alumno> aprobados=aprobados(alumnos);
		System.out.println(aprobados);
	}

	public static List<Alumno> aprobados(List<Alumno> alumnos){
		List<Alumno> res=new ArrayList<Alumno>();
		for(Alumno al:alumnos) {
			if (al.getNota()>=5) {
				res.add(al);
			}
		}
		return res;
	}