Cambios con interfaces

package com.trifulcas.cartas;

public abstract class Carta {
	private String palo;
	private int numero;

	public abstract int getValor();
	
	/**
	 * @return the palo
	 */
	public String getPalo() {
		return palo;
	}

	/**
	 * @param palo the palo to set
	 */
	public void setPalo(String palo) {
		this.palo = palo;
	}

	/**
	 * @return the numero
	 */
	public int getNumero() {
		return numero;
	}

	/**
	 * @param numero the numero to set
	 */
	public void setNumero(int numero) {
		this.numero = numero;
	}

	public String toString() {
		return palo+" | "+numero;
	}
}

package com.trifulcas.cartas;

public class Espanyola extends Carta {

	@Override
	public int getValor() {
		int res = getNumero();

		if (res == 11 || res == 12) {
			res = 10;
		}
		return res;
	}
}

package com.trifulcas.cartas;

public class Francesa extends Carta {

	@Override
	public int getValor() {
		
		return getNumero();
	}
	public void quienSoy() {
		System.out.println("Carta de la baraja Francesa");
	}

}
package com.trifulcas.cartas;

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

public class Baraja implements JuegoAzar {
	private List<Carta> cartas;

	public Baraja() {
		cartas = new ArrayList<Carta>();
	}

	public void addCarta(Carta carta) {
		if (carta instanceof Francesa) {
			Francesa temp=(Francesa)carta;
			temp.quienSoy();
		}
		cartas.add(carta);
	}

	public int totalValor() {
		int res = 0;
		for (Carta carta : cartas) {
			res += carta.getValor();
		}
		return res;
	}

	public String toString() {
		String res = "";
		for (Carta carta : cartas) {
			res += carta + " - ";
		}
		return res;
	}

	@Override
	public void mezclar() {
		System.out.println("Mezclando las cartas");
		
	}
}

package com.trifulcas.cartas;

public interface JuegoAzar {
	public void mezclar();
}

package com.trifulcas.cartas;

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

public class Domino implements JuegoAzar{
	List<String> piezas;

	public Domino() {
		piezas = new ArrayList<String>();
	}
	
	public void esDomino() {
		System.out.println("Dominó");
	}

	@Override
	public void mezclar() {
		System.out.println("Mezclando las fichas");

		
	}
}
package com.trifulcas.cartas;

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

public class TestCartas {

	public static void main(String[] args) {
		Carta sotabastos = new Espanyola();
		sotabastos.setPalo("Bastos");
		sotabastos.setNumero(10);
		System.out.println(sotabastos);
		
		
		Carta sietepicas = new Francesa();
		sietepicas.setNumero(7);
		sietepicas.setPalo("Picas");
		System.out.println(sietepicas);
		((Francesa)sietepicas).quienSoy();

		Francesa cuatrotreboles=new Francesa();
		cuatrotreboles.setNumero(4);
		cuatrotreboles.setPalo("Treboles");
		cuatrotreboles.quienSoy();
		
		Carta reyespadas = new Espanyola();
		reyespadas.setPalo("Espadas");
		reyespadas.setNumero(12);
		System.out.println(reyespadas);

		Baraja miBaraja = new Baraja();
		miBaraja.addCarta(sietepicas);
		miBaraja.addCarta(sotabastos);
		miBaraja.addCarta(reyespadas);
		miBaraja.addCarta(cuatrotreboles);
		
		System.out.println(miBaraja);
		System.out.println(miBaraja.totalValor());
		
		JuegoAzar[] juegos= {new Baraja(),new Domino()};
		
		for(JuegoAzar juego:juegos) {
			if (juego instanceof Domino) {
				((Domino) juego).esDomino();
			}
			juego.mezclar();
		}
	
	}

}

Ejercicio clase abstractas

Vamos a crear la siguiente clase abstracta:

Carta

Que tiene dos propiedades:

String palo
int numero

Con sus getters y setters

Y un método abstracto

getValor()

De ahí vamos a derivar dos clases NO abstractas

Espanyola

Francesa

En Espanyola la función getValor nos devuelve el número que hay en numero EXCEPTO si número es 11 o 12 que devuelve 10.

En Francesa la función getValor nos devuelve siempre el número.

Después podemos crear una clase Baraja que tenga un arraylist de tipo Carta.

Añadimos los métodos addCarta que nos añada una carta al arraylist y un método totalValor que nos sume los valores de las cartas.

package com.trifulcas.cartas;

public abstract class Carta {
	private String palo;
	private int numero;

	public abstract int getValor();
	
	/**
	 * @return the palo
	 */
	public String getPalo() {
		return palo;
	}

	/**
	 * @param palo the palo to set
	 */
	public void setPalo(String palo) {
		this.palo = palo;
	}

	/**
	 * @return the numero
	 */
	public int getNumero() {
		return numero;
	}

	/**
	 * @param numero the numero to set
	 */
	public void setNumero(int numero) {
		this.numero = numero;
	}

	public String toString() {
		return palo+" | "+numero;
	}
}

package com.trifulcas.cartas;

public class Espanyola extends Carta {

	@Override
	public int getValor() {
		int res = getNumero();

		if (res == 11 || res == 12) {
			res = 10;
		}
		return res;
	}

}
package com.trifulcas.cartas;

public class Francesa extends Carta {

	@Override
	public int getValor() {
		
		return getNumero();
	}

}

package com.trifulcas.cartas;

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

public class Baraja {
	private List<Carta> cartas;

	public Baraja() {
		cartas = new ArrayList<Carta>();
	}

	public void addCarta(Carta carta) {
		cartas.add(carta);
	}

	public int totalValor() {
		int res = 0;
		for (Carta carta : cartas) {
			res += carta.getValor();
		}
		return res;
	}
	
	public String toString() {
		String res="";
		for (Carta carta : cartas) {
			res += carta+" - ";
		}
		return res;
	}
}
package com.trifulcas.cartas;

public class TestCartas {

	public static void main(String[] args) {
		Carta sotabastos=new Espanyola();
		sotabastos.setPalo("Bastos");
		sotabastos.setNumero(10);
		System.out.println(sotabastos);

		Carta sietepicas=new Francesa();
		sietepicas.setNumero(7);
		sietepicas.setPalo("Picas");
		System.out.println(sietepicas);
		
		Carta reyespadas=new Espanyola();
		reyespadas.setPalo("Espadas");
		reyespadas.setNumero(12);
		System.out.println(reyespadas);
		
		Baraja miBaraja=new Baraja();
		miBaraja.addCarta(sietepicas);
		miBaraja.addCarta(sotabastos);
		miBaraja.addCarta(reyespadas);
		System.out.println(miBaraja);
		System.out.println(miBaraja.totalValor());
	}

}

¿Cómo acceder a los datos?

Nosotros sabemos acceder a la base de datos vía el conector y sql. Pero nunca vamos a acceder directamente. Siempre colocaremos una capa entre el acceso a la base de datos y el programa.

Esto actualmente se hace de dos maneras: Creando una capa de datos o usando un framework ORM.

¿Que necesitamos?

En primer lugar un POJO que refleje el registro de la base de datos. Es un objeto plano para alamacenar información. COsas básicas: los mismos campos que en la base de datos y setters y getters. Cosas útiles: Un constructor con todos los campos y una sobrecarga de toString.
¿Es necesario que sea igualito que la base de datos? No, pero sí es conveniente.

Si yo en mi base de datos tengo los campos ‘id’ y ‘nombre’ en mi POJO tendré las propiedades ‘id’ y ‘nombre’

private int id;
private String nombre;

Después me creo una capa para conectar con la BD y realizar las operaciones de mantenimento. Se le suele llamar DAO (Data Access Object) . Esto nos separa la base de datos concreta del uso de la misma en el código. Estamos DESACOPLANDO. En programación es importante tener las piezas lo menos dependientes unas de otras.

¿Qué tiene que tener la capa DAO? La funcionalidad básica (CRUD) de acceso a los datos más todas las sobrecargas o métodos que consideremos útiles. Se encargará de recuperar los datos de la base de datos, empaquetarlos en el POJO y mandarlos al usuario. O obtener el POJO del usuario y mapearlo con el registro de la base de datos.

Ejemplos: getActor(), addActor(),….

Una vez creado esto yo puedo utilizar en mi programa el POJO para almacenar información recuperada de la base de datos, para crear información nueva y la capa de datos para tratar con los registros de la base de datos.

Capa de datos (III)

Usar mi capa de datos en un mantenimiento:

package com.trifulcas.datos;


import java.util.List;
import java.util.Scanner;

public class AccesoDAO {

	public static void main(String[] args) {

		try {
			// He abstraído la base de datos
			// Sólo tengo que crear una instancia de mi capa de Datos
			ActorDAO bd = new ActorDAO();

			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;
				switch (res) {
				case 1:
					System.out.println("Buscar actores");

					System.out.println("Dime una parte el apellido");
					String cad = in.next();
					List<Actor> actores = bd.getActors(cad);
					for (Actor actor : actores) {
						System.out.println(actor);
					}

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

					if (bd.addActor(new Actor(0, nombre, apellido, null))) {
						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();

					if (bd.updateActor(new Actor(actor_id, nombre, apellido, null))) {
						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();
					if (bd.deleteActor(actor_id)) {
						System.out.println("Registro eliminado");
					} else {
						System.out.println("No se ha eliminado el registro");
					}
					break;
				}
			} while (res != 0);

		} catch (Exception ex) {

			System.out.println(ex);
		}
	}

}

Capa datos (II)

package com.trifulcas.datos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class ActorDAO {

	private Connection con;
	private int max_records=1000;
	public ActorDAO() {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");

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

	public Actor getActor(int id) {
		Actor res = null;
		try {
			String sql = "select * from actor where actor_id=?" ;
			PreparedStatement stmt = con.prepareStatement(sql);

			stmt.setInt(1, id);

			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				res = new Actor(rs.getInt("actor_id"), rs.getString("first_name"),rs.getString("last_name"),rs.getDate("last_update"));
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}
	
	public List<Actor> getActors(int limite){
		List<Actor> res=new ArrayList<Actor>();
		try {
			String sql = "select * from actor limit ?" ;
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setInt(1, limite);
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				Actor temp = new Actor(rs.getInt("actor_id"), rs.getString("first_name"),rs.getString("last_name"),rs.getDate("last_update"));
				res.add(temp);
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}
	public List<Actor> getActors(){
		return getActors(max_records);
	}

/**
	 * Devuelve un arraylist de actores cuyo apellido contenga la cadena que le pasamos
	 * @param cad cadena a buscar
	 * @return ArrayList de actores
	 */
	public List<Actor> getActors(String cad) {
		List<Actor> res = new ArrayList<Actor>();
		try {
			String sql = "select * from actor where last_name like ?";
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, '%'+cad+'%');
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				Actor temp = new Actor(rs.getInt("actor_id"), rs.getString("first_name"), rs.getString("last_name"),
						rs.getDate("last_update"));
				res.add(temp);
			}

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


	public boolean addActor(Actor actor) {
		try {
			String sql = "insert into actor (first_name, last_name) values (?,?)" ;
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, actor.getFirst_name());
			stmt.setString(2, actor.getLast_name());
			int res=stmt.executeUpdate();
			return res==1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}
	
	public boolean updateActor(Actor actor) {
		try {
			String sql = "update actor set first_name=?, last_name=? where actor_id=?" ;
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setString(1, actor.getFirst_name());
			stmt.setString(2, actor.getLast_name());
			stmt.setInt(3, actor.getActor_id());
			int res=stmt.executeUpdate();
			return res==1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}
	
	public boolean deleteActor(Actor actor) {
		try {
			return deleteActor(actor.getActor_id());
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}
	
	public boolean deleteActor(int actor_id) {
		try {
			String sql = "delete from actor where actor_id=?" ;
			PreparedStatement stmt = con.prepareStatement(sql);
			stmt.setInt(1, actor_id);
			int res=stmt.executeUpdate();
			return res==1;
		} catch (Exception ex) {
			System.out.println(ex);
		}
		return false;
	}

}

package com.trifulcas.datos;

import java.util.List;

public class AccesoDAO {

	public static void main(String[] args) {
		
		// He abstraído la base de datos
		// Sólo tengo que crear una instancia de mi capa de Datos
		ActorDAO bd=new ActorDAO();
		
		// Trabajo exclusivamente con POJO no con registros de la base de datos
		// Que hasta desconozco o no me interesa como están implementados
		Actor penelope=bd.getActor(1);
		
		System.out.println(penelope.getFirst_name());

		// Obtengo todos los actores en una lista y recorro la lista
		List<Actor> actores=bd.getActors(20);
		for(Actor actor:actores) {
			System.out.println(actor);
		}
		
		// Para añadir creo un actor nuevo y después llamo a la capa DAO para añadirlo
		Actor nuevo=new Actor(1,"wilfredo","etxevarria",null);
		if(bd.addActor(nuevo)) {
			System.out.println("Actor "+nuevo+" añadido");
		}
		
		// Modifico un actor
		penelope.setLast_name("Campofrío");
		bd.updateActor(penelope);
		
		// Elimino el actor concreto o por id
		Actor w=bd.getActor(320);
		bd.deleteActor(w);
		bd.deleteActor(321);
	}

}

Capa DAO (I)

Primero creamos el POJO:

package com.trifulcas.datos;

import java.sql.Date;

public class Actor {

	private int actor_id;
	private String first_name;
	private String last_name;
	private Date last_update;
	
	public Actor(int actor_id, String first_name, String last_name, Date last_update) {
		super();
		this.actor_id = actor_id;
		this.first_name = first_name;
		this.last_name = last_name;
		this.last_update = last_update;
	}
	
	/**
	 * @return the actor_id
	 */
	public int getActor_id() {
		return actor_id;
	}
	/**
	 * @param actor_id the actor_id to set
	 */
	public void setActor_id(int actor_id) {
		this.actor_id = actor_id;
	}
	/**
	 * @return the first_name
	 */
	public String getFirst_name() {
		return first_name;
	}
	/**
	 * @param first_name the first_name to set
	 */
	public void setFirst_name(String first_name) {
		this.first_name = first_name;
	}
	
	/**
	 * @return the last_name
	 */
	public String getLast_name() {
		return last_name;
	}
	/**
	 * @param last_name the last_name to set
	 */
	public void setLast_name(String last_name) {
		this.last_name = last_name;
	}
	/**
	 * @return the last_update
	 */
	public Date getLast_update() {
		return last_update;
	}
	/**
	 * @param last_update the last_update to set
	 */
	public void setLast_update(Date last_update) {
		this.last_update = last_update;
	}
	
	public String toString() {
		return actor_id+" | "+first_name+" | "+last_name+" | "+last_update;
	}
	
}

Capa de datos:

package com.trifulcas.datos;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class ActorDAO {

	private Connection con;

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

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

	public Actor getActor(int id) {
		Actor res = null;
		try {
			String sql = "select * from actor where actor_id=?" ;
			PreparedStatement stmt = con.prepareStatement(sql);

			stmt.setInt(1, id);

			ResultSet rs = stmt.executeQuery();
			if (rs.next()) {
				res = new Actor(rs.getInt("actor_id"), rs.getString("first_name"),rs.getString("last_name"),rs.getDate("last_update"));
			}

		} catch (Exception ex) {
			System.out.println(ex);
		}
		return res;
	}
	
	public List<Actor> getActors(){
		List<Actor> res=new ArrayList<Actor>();
		try {
			String sql = "select * from actor " ;
			PreparedStatement stmt = con.prepareStatement(sql);
			ResultSet rs = stmt.executeQuery();
			while (rs.next()) {
				Actor temp = new Actor(rs.getInt("actor_id"), rs.getString("first_name"),rs.getString("last_name"),rs.getDate("last_update"));
				res.add(temp);
			}

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

}

Ejemplo de uso:

package com.trifulcas.datos;

import java.util.List;

public class AccesoDAO {

	public static void main(String[] args) {
		
		// He abstraído la base de datos
		ActorDAO bd=new ActorDAO();
		
		Actor penelope=bd.getActor(1);
		
		System.out.println(penelope.getFirst_name());

		List<Actor> actores=bd.getActors();
		for(Actor actor:actores) {
			System.out.println(actor);
		}
		
		Actor nuevo=new Actor(1,"w","e",null);
	}

}

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