
Este patrón no solo da un orden a nuestro código separando las funciones de una clase frente a otras acciones, si no que facilita la adaptación o actualización a otros sistemas. Imagínate que tienes un sistema montado en producción con una base de datos MySQL y la quieres cambiar a Mongo, o utilizar Hibernate o a cualquier otro motor de base de datos.
La capa DAO contiene todos los métodos CRUD (create, read, update, delete), por lo general se tiene un DAO para cada tabla en la base de datos, y la implementación se la realiza de la siguiente manera.
Pongamos que tenemos una clase Persona con sus atributos y métodos setters &getters
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
package ejercicio1; import java.io.Serializable; import java.sql.Date; public class Persona { private String dni; private String nombre; private Date fechaNacimiento; private String direccion; private int telefono; Persona(String dni, String nombre, Date fechaNacimiento, String direccion, int telefono){ this.dni = dni; this.nombre = nombre; this.fechaNacimiento = fechaNacimiento; this.direccion = direccion; this.telefono = telefono; } public String getDni() { return dni; } public void setDni(String dni) { this.dni = dni; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public Date getFechaNacimiento() { return fechaNacimiento; } public void setFechaNacimiento(Date fechaNacimiento) { this.fechaNacimiento = fechaNacimiento; } public String getDireccion() { return direccion; } public void setDireccion(String direccion) { this.direccion = direccion; } public int getTelefono() { return telefono; } public void setTelefono(int telefono) { this.telefono = telefono; } @Override public String toString() { return "Persona [dni=" + dni + ", nombre=" + nombre + ", fechaNacimiento=" + fechaNacimiento + ", direccion=" + direccion + ", telefono=" + telefono + "]"; } } |
Luego implementamos la clase DAO para los métodos de manipulación de datos de la clase anterior persona.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
package ejercicio1; import java.sql.*; import java.util.ArrayList; import java.util.List; public class PersonasDAO { private Connection conexion; public void abrirConexion() { try { // Cargar el driver de mySQL Class.forName("com.mysql.jdbc.Driver"); // Establecer la conexion con la Base de Datos conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/censo", "root", "password"); } catch (ClassNotFoundException e) { System.out.println("Error al cargar el driver"); e.printStackTrace(); } catch (SQLException e) { System.out.println("Error al establecer la conexion"); e.printStackTrace(); } } public void cerrarConexion() { try { conexion.close(); } catch (SQLException e) { System.out.println("Error al cerrar la conexion"); e.printStackTrace(); } } public String altaPersona(Persona p) throws SQLException { String mensaje = "No se pudo dar de alta a la persona"; PreparedStatement stm; try { //conexion.setAutoCommit(false); abrirConexion(); stm = conexion.prepareStatement("INSERT INTO censo.persona VALUES (?,?,?,?,?)"); stm.setString(1, p.getDni()); stm.setString(2, p.getNombre()); stm.setDate(3, p.getFechaNacimiento()); stm.setString(4, p.getDireccion()); stm.setInt(5, p.getTelefono()); int resultados = stm.executeUpdate(); if (resultados == 1) { mensaje = "Alta OK"; //conexion.commit(); } } catch (SQLException e) { //conexion.rollback(); e.printStackTrace(); } finally { cerrarConexion(); } return mensaje; } public String bajaPersona(Persona p) throws SQLException { String mensaje = "No se pudo dar de baja a la persona"; PreparedStatement stm; try { abrirConexion(); stm = conexion.prepareStatement("DELETE FROM censo.persona WHERE DNI=?"); stm.setString(1, p.getDni()); int resultados = stm.executeUpdate(); if (resultados == 1) { mensaje = "Baja OK"; } } catch (SQLException e) { e.printStackTrace(); } finally { cerrarConexion(); } return mensaje; } public String modificarPersona(Persona p, int telefonoNuevo) throws SQLException { String mensaje = "No se pudo modificar la persona llamada " + p.getNombre(); PreparedStatement stm; try { abrirConexion(); stm = conexion.prepareStatement(" UPDATE censo.persona SET TFNO=? WHERE DNI=?"); stm.setInt(1, telefonoNuevo); stm.setString(2, p.getDni()); int resultados = stm.executeUpdate(); if (resultados == 1) { mensaje = "Modificaci�n Tel�fono OK"; } } catch (SQLException e) { e.printStackTrace(); } finally { cerrarConexion(); } return mensaje; } public List<Persona> consultarTodasPersonas() { PreparedStatement stm; List<Persona> lista = new ArrayList<Persona>(); try { abrirConexion(); stm = conexion.prepareStatement(" SELECT * FROM censo.persona"); ResultSet resultados = stm.executeQuery(); while (resultados.next()) { lista.add(new Persona(resultados.getString("DNI"), resultados.getString("NOMBRE"), resultados.getDate("FECNAC"), resultados.getString("DIR"), resultados.getInt("TFNO"))); } } catch (SQLException e) { System.out.println("Error al consultar todos"); e.printStackTrace(); } finally { cerrarConexion(); } return lista; } } |
Por último se prueba el patrón DAO desde un main.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package ejercicio1; import java.sql.Date; import java.sql.SQLException; public class Main { public static void main(String[] args) { PersonasDAO pdao = new PersonasDAO(); Persona p = new Persona("78565665P", "Pedro P�rez", new Date(1975 - 01 - 01), "Calle Lleida 5, 7, 3", 936852666); Persona p1 = new Persona("Y85212121", "Mario Ruiz", new Date(1955 - 12 - 07), "Calle Milla 4, p, 1", 936121212); Persona p2 = new Persona("0898900", "Maria Matera", new Date(1980 - 10 - 31), "Calle Verde 9, 3, 1", 936712893); try { System.out.println(pdao.altaPersona(p)); System.out.println(pdao.altaPersona(p1)); System.out.println(pdao.altaPersona(p2)); System.out.println("Censo inicial*******************************************"); for (Persona per : pdao.consultarTodasPersonas()) { System.out.println(per); } System.out.println(pdao.bajaPersona(p)); System.out.println(pdao.modificarPersona(p2, 111111111)); } catch (SQLException e) { e.printStackTrace(); } System.out.println("Censo final *******************************************"); for (Persona per : pdao.consultarTodasPersonas()) { System.out.println(per); } } } |
De este modo podemos separar la lógica del modelo de los metodos de inserción, siendo capaces de separar en todo momento una de las capas para su modificación.
Veamos la clase DAO con mas detalle:
Podemos diferenciar claramente los métodos de manipulación, como son la inserción, actualización listado de datos o borrado, de los métodos de conexión.
Tenemos los métodos abrir conexión y cerrar conexión para no tener que repetir en cada método este proceso.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public void abrirConexion() { try { // Cargar el driver de mySQL Class.forName("com.mysql.jdbc.Driver"); // Establecer la conexion con la Base de Datos conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/censo", "root", "password"); } catch (ClassNotFoundException e) { System.out.println("Error al cargar el driver"); e.printStackTrace(); } catch (SQLException e) { System.out.println("Error al establecer la conexion"); e.printStackTrace(); } } |
|
1 2 3 4 5 6 7 8 9 |
public void cerrarConexion() { try { conexion.close(); } catch (SQLException e) { System.out.println("Error al cerrar la conexion"); e.printStackTrace(); } } |
De tal manera que luego realizaremos cada método del CRUD conectándonos y desconectándonos cada vez.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public String altaPersona(Persona p) throws SQLException { String mensaje = "No se pudo dar de alta a la persona"; PreparedStatement stm; try { //conexion.setAutoCommit(false); abrirConexion(); stm = conexion.prepareStatement("INSERT INTO censo.persona VALUES (?,?,?,?,?)"); stm.setString(1, p.getDni()); stm.setString(2, p.getNombre()); stm.setDate(3, p.getFechaNacimiento()); stm.setString(4, p.getDireccion()); stm.setInt(5, p.getTelefono()); int resultados = stm.executeUpdate(); if (resultados == 1) { mensaje = "Alta OK"; //conexion.commit(); } } catch (SQLException e) { //conexion.rollback(); e.printStackTrace(); } finally { cerrarConexion(); } return mensaje; } |