jueves, 17 de octubre de 2019

Creando JSP con acceso a base de datos

Debemos tener un "index.html" donde colocaremos nuestro menú para las diversas acciones, este puede ser modificado posteriormente por un "login" para manejar accesos.

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <a href="inquilinos.jsp">Mantenimiento a inquilinos</a>
    </body>
</html>


Primera llamada al Servlet

Tenemos el JSP que nos llevará al listado de "inquilinos", este llama al Servlet (clic aquí para ver el Servlet) de nombre "Inquilinos" y como parámetro "accion" es valor es "SEL", en el Servlet podemos observar que la acción SEL no se varía el "target", por lo que nos llevaría al "target" por defecto que es: "inquilinosSel.jsp". Es importante este pequeño archivo, ya que de lo contrario no le diríamos de ninguna forma al Servlet que acción debe realizar y no haría nada, pero se puede reemplazar con otros métodos más sencillos.

<%response.sendRedirect("Inquilinos?accion=SEL");%>
  


Lectura de datos y despliegue en una tabla HTML

En "inquilinosSel.jsp" tendremos una tabla en la que empleando la biblioteca JSTL con la función "foreach" le colocamos los valores de la consulta SELECT a la base de datos.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Mantenimiento de inquilinos</title>
        <script src="jq/jquery-3.3.1.min.js" type="text/javascript"></script>
        <script src="js/inquilinos.js" type="text/javascript"></script>
    </head>
    <body>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
        <table border="1">
            <thead>
                <tr>
                    <th>
                        <a href="#" onclick="inquilinosIns();">
                            Agregar                            
                        </a>
                    </th>
                    <th>ID</th>
                    <th>DNI</th>
                    <th>NOMBRES</th>
                    <th>PATERNO</th>
                    <th>MATERNO</th>
                    <th>TELEFONO</th>
                    <th>FECHA DE INGRESO</th>
                    <th>CORREO</th>
                    <th>DEUDAS</th>
                    <th>
                        <a href="#" onclick="inquilinosUpd();">
                            Actualizar                            
                        </a>
                    </th>
                    <th>
                        <a href="#" onclick="inquilinosDel();">
                            Eliminar                         
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
            <c:forEach var="f" items="${list}">                
                <tr>
                    <td colspan="2">${f.idinquilinos}</td>
                    <td>${f.dni}</td>
                    <td>${f.nombres}</td>
                    <td>${f.paterno}</td>
                    <td>${f.materno}</td>
                    <td>${f.telefono}</td>
                    <td>${f.fecha_ingreso}</td>
                    <td>${f.correo}</td>
                    <td>${f.deuda}</td>
                    <th>
                        <input type="radio" name="id_upd"
                               value="${f.idinquilinos}"/>
                    </th>
                    <th>
                        <input type="checkbox" name="id_del" 
                               value="${f.idinquilinos}"/>
                    </th>
                </tr>
            </c:forEach> 
        </tbody>
    </table>
</body>
</html>

Nos mostrará un resultado como este:
Agregar ID DNI NOMBRES PATERNO MATERNO TELEFONO FECHA DE INGRESO CORREO DEUDAS Actualizar Eliminar
1 31378082 LUISA PAUCAR NARRO 999888777 2018-01-28 lpaucar@mail.com 0.0
2 43331042 AUGUSTO SOTOMAYOR NARVAJO 900800700 2019-10-08 asoto@mail.com 0.0

Agregando datos desde un formulario HTML a la base de datos

Podemos agregar un registro mediante un formulario, este no es necesario que sea un JSP, puede ser un HTML, pero si queremos mostrar un mensaje de error que llegue directamente desde el Servlet, será necesario que sea un JSP. Este archivo se llama: "inquilinosIns.jsp"

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
        
    </head>
    <body>
        <h1>Agregar inquilino</h1>
        <form action="Inquilinos" method="post" style="margin: auto; display: table"> 
            <input type="hidden" name="accion" value="INS"/>
            <fieldset>
                <legend>Agregar datos</legend>
                <br/>
                <input type="text" name="dni" style="width: 400px"
                       placeholder="Ingrese el DNI"/>
                <br/>
                <input type="text" name="nombres" style="width: 400px"
                       placeholder="Ingrese el nombre"/>
                <br/>
                <input type="text" name="paterno" style="width: 400px"
                       placeholder="Ingrese el apellido paterno"/>
                <br/>
                <input type="text" name="materno" style="width: 400px"
                       placeholder="Ingrese el apellido materno"/>
                <br/>
                <input type="text" name="telefono" style="width: 400px"
                       placeholder="Ingrese el telefono"/>
                <br/>
                <label>Ingrese la fecha de ingreso</label> 
                <input type="date" name="fecha_ingreso" style="width: 400px"/>
                <br/>
                <label>Ingrese la deuda</label> 
                <input type="number" name="deuda" style="width: 400px"/>
                <br/>
                <input type="email" name="correo" style="width: 400px"
                       placeholder="Ingrese el correo"/>
                <br/>    
                <br/><p style="text-align: center;">
                    <button type="submit">Agregar</button>
                </p>               
            </fieldset>
        </form>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
    </body>
</html>


Actualizando datos desde un formulario HTML a la base de datos

Podemos actualizar un registro mediante un formulario, este debe ser un JSP, ya que vamos a cargar los datos del registro a actualizar en el formulario de actualización, vemos como aparecen los atributos "value" en los elementos HTML "input", el nombre debe coincidir con el dado en el "validator". Este archivo se llama: "inquilinosUpd.jsp"

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>
        <h1>Actualizar inquilino</h1>
        <form action="Inquilinos" method="post" style="margin: auto; display: table"> 
            <input type="hidden" name="accion" value="UPD"/>
            <input type="hidden" name="idinquilinos" value="${inquilino.idinquilinos}"/>
            <fieldset>
                <legend>Actualizar datos</legend>
                <br/>
                <input type="text" name="dni" style="width: 400px"
                       placeholder="Ingrese el DNI" 
                       value="${inquilino.dni}"/>
                <br/>
                <input type="text" name="nombres" style="width: 400px"
                       placeholder="Ingrese el nombre" 
                       value="${inquilino.nombres}"/>
                <br/>
                <input type="text" name="paterno" style="width: 400px"
                       placeholder="Ingrese el apellido paterno" 
                       value="${inquilino.paterno}"/>
                <br/>
                <input type="text" name="materno" style="width: 400px"
                       placeholder="Ingrese el apellido materno" 
                       value="${inquilino.materno}"/>
                <br/>
                <input type="text" name="telefono" style="width: 400px"
                       placeholder="Ingrese el telefono" 
                       value="${inquilino.telefono}"/>
                <br/>
                <label>Ingrese la fecha de ingreso</label> 
                <input type="date" name="fecha_ingreso" style="width: 400px" 
                       value="${inquilino.fecha_ingreso}"/>
                <br/>
                <label>Ingrese la deuda</label> 
                <input type="number" name="deuda" style="width: 400px" 
                       value="${inquilino.deuda}"/>
                <br/>
                <input type="email" name="correo" style="width: 400px"
                       placeholder="Ingrese el correo" 
                       value="${inquilino.correo}"/>
                <br/>    
                <br/><p style="text-align: center;">
                    <button type="submit">Actualizar</button>
                </p>               
            </fieldset>
        </form>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
    </body>
</html>


Funciones JavaScript de apoyo

La navegación entre páginas es relativamente compleja si no empleamos funciones de JavaScript que nos ayudan incluso a mostrar algunos mensjaes de alerta. Este archivo se llama: "inquilinos.js" y se debe colocar en una carpeta llamada "js". Todo este embrollo de colocarlos en carpetas es muy útil para mantener un orden y trabajar de forma estandarizada.

function inquilinosIns() {
    window.location = "inquilinosIns.jsp";
}

function inquilinosDel() {
    var ids = [];
    $("input[name='id_del']:checked").each(function () {
        ids.push($(this).val());
    });
    if (ids.length === 0) {
        alert("Advertencia\n\nSeleccione la(s) fila(s) a Retirar");
    } else {
        var exito = confirm('¿Seguro que deseas borrar los registros?');
        if (exito) {
            window.location = "Inquilinos?accion=DEL&ids=" + ids.toString();
        } else {
            alert("Operación cancelada");
        }
    }
}

function inquilinosUpd() {    
    var id = $("input[name='id_upd']:checked").val();
    if (isNaN(id)) {
        alert("Seleccione Fila para Actualizar Datos");
    } else {
        window.location = "Inquilinos?accion=GET&idinquilino=" + id;
    }
}


Estas funciones son llamadas en la pantalla "inquilinosSel.jsp" en los botones de eliminar, actualizar o agregar.

Estructura de carpetas y archivos

Tendremos la siguiente estructura, es necesario incluir al JQuery parapoder trabajar de forma más sencilla con el código JS, pero no es necesario si se modifican las funciones de JS que lo emplean. Aún así es importante recalcar que prácticamente todos los Frameworks de FrontEnd emplean a esta biblioteca de JavaScript.



Servlets

¿Qué es un Servlet?

Se le llama así a una de las tecnologías proporcionadas por Java que generan componentes independientes que serán empleados en aplicaciones web, estos tienen acceso completo a las API de Java y las bibliotecas de HTTP. Los servlets están intimanente ligados a la plataforma y el servidor.

¿Cómo crear un Servlet en NetBeans?

Seguir los pasos:


¿Qué debemos modificar?

Cambiar el nombre de acuerdo a la función que hará o tabla que dará mantenimiento, colocarlo por preferencia en un paquete que contendrá a los servlets, en algunos casos podemos llamarlos controllers haciendo referencia al patrón MVC.

Modificar el alias del Servlet a uno que no incluya la terminación servlet y finalizar.


Código de ejemplo

Teniendo como base a la tabla "Inquilinos"(clic aquí para ver el DTO) a la que le realizaremos un mantenimiento (CRUD) teniendo como DAO a "DaoInquilinos" y su correspondiente implementación (clic aquí para ver el DAO).Además, las pruebas a las funciones declaradas en el DAO (clic aquí para ver el DAO).

Crearemos dos paquetes dentro del paquete web que serán "servlet" y "validator", dentro crearemos respectivamente el servlet llamado "InquilinosServlet" y una clase de apoyo llamada "InquilinosValidator", esta untima clase nos sirve para reducir la cantidad de código en el Servlet y poder tener mejor mantenimiento de este, por lo tanto es opcional.

Tendríamos el código de "InquilinosValidator" considerando las funciones que declaramos en el DAO, de la siguiente forma:
package web.validator;

import biblioteca.DeString;
import dao.DaoInquilinos;
import dao.impl.DaoInquilinosImpl;
import dto.Inquilinos;
import java.time.LocalDate;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

public class InquilinosValidator {

    private final HttpServletRequest request;
    private final DaoInquilinos daoInquilinos;

    public InquilinosValidator(HttpServletRequest request) {
        this.request = request;
        this.daoInquilinos = new DaoInquilinosImpl();
    }

    public String inquilinosSel() {
        String result = null;
        List<Inquilinos> list = daoInquilinos.inquilinosSel();
        if (list != null) {
            request.setAttribute("list", list);
        } else {
            result = daoInquilinos.getMessage();
        }
        return result;
    }

    public String inquilinosGet() {
        String result = null;
        Integer idinquilino = DeString.aInteger(request.getParameter("idinquilino"));
        Inquilinos inquilino = daoInquilinos.inquilinosGet(idinquilino);
        if (inquilino != null) {
            request.setAttribute("inquilino", inquilino);

        } else {
            result = daoInquilinos.getMessage();
        }
        return result;
    }

    public String inquilinosInsUpd(boolean upd) {
        StringBuilder result = new StringBuilder("<ul>");
        Integer idinquilino = DeString.aInteger(request.getParameter("idinquilinos"));
        String dni = request.getParameter("dni");
        String nombres = request.getParameter("nombres");
        String paterno = request.getParameter("paterno");
        String materno = request.getParameter("materno");
        String telefono = request.getParameter("telefono");
        LocalDate fecha_ingreso = LocalDate.parse(request.getParameter("fecha_ingreso"));
        String correo = request.getParameter("correo");
        Double deuda = DeString.aDouble(request.getParameter("deuda"));
        if (upd && idinquilino == null) {
            result.append("<li>Id requerido</li>");
        }
        if (nombres == null || nombres.trim().length() == 0) {
            result.append("<li>Nombre requerido</li>");
        } else if (nombres.trim().length() < 3 || nombres.trim().length() > 50) {
            result.append("<li>La dimensión del nombre debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (paterno == null || paterno.trim().length() == 0) {
            result.append("<li>Apellido paterno requerido</li>");
        } else if (paterno.trim().length() < 3 || paterno.trim().length() > 50) {
            result.append("<li>La dimensión del apellido paterno debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (materno == null || materno.trim().length() == 0) {
            result.append("<li>Apellido materno requerido</li>");
        } else if (materno.trim().length() < 3 || materno.trim().length() > 50) {
            result.append("<li>La dimensión del apellido materno debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (fecha_ingreso == null) {
            result.append("<li>Fecha requerida</li>");
        }
        if (deuda < 0d) {
            result.append("<li>La deuda no puede ser negativa</li>");
        }
        Inquilinos inquilino = new Inquilinos();
        inquilino.setIdinquilinos(idinquilino);
        inquilino.setDni(dni);
        inquilino.setNombres(nombres);
        inquilino.setPaterno(paterno);
        inquilino.setMaterno(materno);
        inquilino.setFecha_ingreso(fecha_ingreso);
        inquilino.setTelefono(telefono);
        inquilino.setDeuda(deuda);
        inquilino.setCorreo(correo);
        if (result.length() == 4) {
            String msg = upd
                    ? daoInquilinos.inquilinosUpd(inquilino)
                    : daoInquilinos.inquilinosIns(inquilino);
            if (msg != null) {
                result.append("<li>").append(msg).append("</li>");
            }
        }
        if (result.length() > 4) {
            request.setAttribute("inquilino", inquilino);
        }
        return result.length() == 4 ? null : result.append("</ul>").toString();
    }

    public String inquilinosDel() {
        List<Integer> ids = DeString.ids(request.getParameter("ids"));
        String result = (ids != null)
                ? daoInquilinos.inquilinosDel(ids)
                : "IDs incorrectos";
        return result;
    }
}

Mientras el código del Servlet sería:

package web.servlet;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import web.validator.InquilinosValidator;

@WebServlet(name = "InquilinosServlet", urlPatterns = {"/Inquilinos"})
public class InquilinosServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        String accion = request.getParameter("accion");
        accion = (accion == null) ? "" : accion;
        String result;
        String target = "inquilinosSel.jsp";

        InquilinosValidator validator = new InquilinosValidator(request);

        switch (accion) {
            case "SEL":
                result = validator.inquilinosSel();
                break;
            case "INS":
                result = validator.inquilinosInsUpd(false);
                target = result == null ? "inquilinos.jsp" : "inquilinosIns.jsp";
                break;
            case "DEL":
                result = validator.inquilinosDel();
                target = "inquilinos.jsp";
                break;
            case "GET":
                result = validator.inquilinosGet();
                target = "inquilinosUpd.jsp";
                break;
            case "UPD":
                result = validator.inquilinosInsUpd(true);
                target = result == null ? "inquilinos.jsp" : "inquilinosUpd.jsp";
                break;
            case "":
                result = "Solicitud requerida";
                break;
            default:
                result = "Solicitud no reconocida";
        }

        if (result != null) {
            request.setAttribute("message", result);
        }

        RequestDispatcher dispatcher = request.getRequestDispatcher(target);
        dispatcher.forward(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }

}

La estructura de carpetas resultaría en:

La clase DeString es una librería interna. (clic aquí para ver el código), esta permite convertir String a Integer y Double, incluso en colecciones tipo List.

domingo, 13 de octubre de 2019

Pruebas simples a un DAO

Estructura

Crear un paquete de pruebas que llamaremos "test", dentro un "Java Main Class" que se llamará "TestDaoInquilinos "


Código

Probamos cada una de las funciones de la clase DAO, en este caso del "DaoInquilinos" (clic aquí para ver el código del DAO)

Probando el listado de registros

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
List<Inquilinos> list = daoInquilinos.inquilinosSel();
if (list != null) {
 try {
  list.forEach((t) -> {
   System.out.println(t.getIdinquilinos().toString() + " "
    + t.getDni() + " "
    + t.getNombres() + " "
    + t.getPaterno() + " "
    + t.getMaterno() + " "
    + t.getTelefono() + " "
    + t.getCorreo() + " "
    + t.getDeuda().toString() + " "
    + t.getFecha_ingreso().toString());
  });
 } catch (Exception e) {
  System.out.println(daoInquilinos.getMessage());
  System.out.println(e.getMessage());
 }
} else {
 System.out.println("Lista vacía");
}


Probando el obtener un registro por su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = daoInquilinos.inquilinosGet(1);
if (inquilino != null) {
 try {
  System.out.println(inquilino.getIdinquilinos().toString() + " "
    + inquilino.getDni() + " "
    + inquilino.getNombres() + " "
    + inquilino.getPaterno() + " "
    + inquilino.getMaterno() + " "
    + inquilino.getTelefono() + " "
    + inquilino.getCorreo() + " "
    + inquilino.getDeuda().toString() + " "
    + inquilino.getFecha_ingreso().toString());
 } catch (Exception e) {
  System.out.println(daoInquilinos.getMessage());
  System.out.println(e.getMessage());
 }
} else {
 System.out.println("Usuario no encontrado");
}


Probando el insertar un nuevo registro

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = new Inquilinos();
inquilino.setDni("71005052");
inquilino.setNombres("ROBERT");
inquilino.setPaterno("JONES");
inquilino.setMaterno("SMITH");
inquilino.setTelefono("997777822");
inquilino.setCorreo("robert@mail.com");
inquilino.setDeuda(0d);
inquilino.setFecha_ingreso(LocalDate.parse("2010-12-18"));
try {
 daoInquilinos.inquilinosIns(inquilino);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Probando la actualización de un registro ingresando su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = new Inquilinos();
inquilino.setIdinquilinos(5);
inquilino.setDni("79905052");
inquilino.setNombres("PAUL");
inquilino.setPaterno("WAYNE");
inquilino.setMaterno("DIAZ");
inquilino.setTelefono("998484822");
inquilino.setCorreo("paul@mail.com");
inquilino.setDeuda(0d);
inquilino.setFecha_ingreso(LocalDate.parse("2012-12-28"));
try {
 daoInquilinos.inquilinosUpd(inquilino);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Probando la eliminación de un registro por su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
List<Integer> del = new ArrayList<>();
del.add(4);
del.add(3);
try {
 daoInquilinos.inquilinosDel(del);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Clase de pruebas

Crear un paquete de pruebas que llamaremos "test", dentro un "Java Main Class" que se llamará "TestDaoInquilinos" donde implementaremos todo el código anterior en un solo archivo para probar todas las funcionalidades en un solo archivo

package test;

import dao.DaoInquilinos;
import dao.impl.DaoInquilinosImpl;
import dto.Inquilinos;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class TestDaoInquilinos {

    public static void main(String[] args) throws ParseException {
        Scanner scanner;
        DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
        Inquilinos inquilino;
        Integer opt;
        do {
            scanner = new Scanner(System.in);
            inicio();
            opt = scanner.nextInt();
            switch (opt) {
                case 1:
                    List<inquilinos> list = daoInquilinos.inquilinosSel();
                    if (list != null) {
                        try {
                            list.forEach((t) -> {
                                System.out.println(t.getIdinquilinos().toString() + " "
                                        + t.getDni() + " "
                                        + t.getNombres() + " "
                                        + t.getPaterno() + " "
                                        + t.getMaterno() + " "
                                        + t.getTelefono() + " "
                                        + t.getCorreo() + " "
                                        + t.getDeuda().toString() + " "
                                        + t.getFecha_ingreso().toString());
                            });
                        } catch (Exception e) {
                            System.out.println(daoInquilinos.getMessage());
                            System.out.println(e.getMessage());
                        }
                    } else {
                        System.out.println("Lista vacía");
                    }
                    break;
                case 2:
                    inquilino = daoInquilinos.inquilinosGet(1);
                    if (inquilino != null) {
                        try {
                            System.out.println(inquilino.getIdinquilinos().toString() + " "
                                    + inquilino.getDni() + " "
                                    + inquilino.getNombres() + " "
                                    + inquilino.getPaterno() + " "
                                    + inquilino.getMaterno() + " "
                                    + inquilino.getTelefono() + " "
                                    + inquilino.getCorreo() + " "
                                    + inquilino.getDeuda().toString() + " "
                                    + inquilino.getFecha_ingreso().toString());
                        } catch (Exception e) {
                            System.out.println(daoInquilinos.getMessage());
                            System.out.println(e.getMessage());
                        }
                    } else {
                        System.out.println("Usuario no encontrado");
                    }
                    break;
                case 3:
                    inquilino = new Inquilinos();
                    inquilino.setDni("71005052");
                    inquilino.setNombres("ROBERT");
                    inquilino.setPaterno("JONES");
                    inquilino.setMaterno("SMITH");
                    inquilino.setTelefono("997777822");
                    inquilino.setCorreo("robert@mail.com");
                    inquilino.setDeuda(0d);
                    inquilino.setFecha_ingreso(LocalDate.parse("2010-12-18"));
                    try {
                        daoInquilinos.inquilinosIns(inquilino);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 4:
                    inquilino = new Inquilinos();
                    inquilino.setIdinquilinos(5);
                    inquilino.setDni("79905052");
                    inquilino.setNombres("PAUL");
                    inquilino.setPaterno("WAYNE");
                    inquilino.setMaterno("DIAZ");
                    inquilino.setTelefono("998484822");
                    inquilino.setCorreo("paul@mail.com");
                    inquilino.setDeuda(0d);
                    inquilino.setFecha_ingreso(LocalDate.parse("2012-12-28"));
                    try {
                        daoInquilinos.inquilinosUpd(inquilino);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 5:
                    List<integer> del = new ArrayList<>();
                    del.add(4);
                    del.add(3);

                    try {
                        daoInquilinos.inquilinosDel(del);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 6:
                    System.out.println("Adios");
                    break;
                default:
                    System.out.println("Opción incorrecta");
            }
        } while (opt != 6);
    }

    private static void inicio() {
        System.out.println("--------Claves de las prueba-----");
        System.out.println("1: Lista de usuarios UsuariosSel");
        System.out.println("2: Obtener usuario UsuariosGet");
        System.out.println("3: Insertar usuario UsuariosUpd");
        System.out.println("4: Actualizar usuario UsuariosIns");
        System.out.println("5: Eliminar usuario UsuariosDel");
        System.out.println("6: Salir");
        System.out.println("-----------------------------------");
        System.out.print("\nIngrese la clave: ");
    }
}

Crear un proyecto web con Java en NetBeans 8.2

Debemos seguir los siguientes pasos:


Primero: debemos iniciar el NetBeans, acto seguido seleccionar en "File" o "Archivo" la opción de "New Project..." o "Nuevo Proyecto...". También, podemos usar la combinación de teclas Ctrl + Shift + N o darle clic a la metáfora de nuevo proyecto como se observa en la siguiente imagen.

Fuente: elaboración propia.

Segundo: luego aparecerá una ventana flotante donde seleccionaremos la categoría "Java Web" y el tipo de proyecto "Web Application".

Fuente: elaboración propia.

Tercero:Luego debemos elegir un nombre para el proyecto y su ubicación.

Fuente: elaboración propia.

Cuarto:Seleccionar el servidor, la versión del Java EE y la ruta: en este caso se eligió el Tomcat (puede ser GlassFish), la versión 7 del EE y la ruta será /Demo.

Fuente: elaboración propia.

Quinto: Luego podemos elegir un Framework, dependiendo de la envergadura del proyecto se elige uno o ninguno.

Fuente: elaboración propia.

Sexto:Finalmente, comprobamos la creación del proyecto.

Fuente: elaboración propia.



Ahora podemos empezar a programar las distintas partes de nuestro proyecto.

Conectar MySql o MariaBD con Java (NetBeans)

Se necesita lo siguiente:
  • NetBeans IDE 8.2 o superior.
  • Tener instalado el JDK versión 8 o superior.
  • Tener Instalado MySql versión  5.7.24 o superior, en caso de MariaBD la versión 10.3.12 o superior

El servidor de bases de datos

En este caso debemos tener conocimiento del URL de la base de datos, el puerto que emplea (3306 para MySql y 3307 para MariaBD), el usuario y contraseña.

Creamos una clase llamada "ConectaBD" dentro del paquete "biblioteca" y definimos 4 constantes:
  • URL: que contiene la dirección del servidor de base de datos, en este caso "jdbc:mysql".
  • DRIVER: dirección del driver de conexión de bases de datos, en este caso el driver de MySQL.
  • USER: el usuario, en este caso usamos root.
  • PASS: la constraseña, en este caso está vacía.
El código sería:

package biblioteca;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


public class ConectaBD {
    private final String URL = "jdbc:mysql://localhost:3306/blog";
    private final String DRIVER = "com.mysql.jdbc.Driver";
    private final String USER = "root";
    private final String PASS = "";
    
    public Connection conexionDB() throws SQLException{
    Connection c = null;
        try {
            Class.forName(DRIVER).newInstance();
            c = DriverManager.getConnection(URL, USER, PASS);
        } catch (ClassNotFoundException | 
                 IllegalAccessException | 
                 InstantiationException | 
                 SQLException e) {
            throw new SQLException(e.getMessage());
        }
    
    return c;
    }
}


Se emplea las clases: "Connection", "DriverManager" y "SQLException".

DAO - Objeto de acceso a datos

Los DAO permiten mantener separado el acceso a los datos que pueden provenir de bases de datos, servicios web u otros de las demás tareas que realiza la aplicación, de esta forma las otras partes del programa no deben preocuparse del acceso a los datos, solamente de realizar sus tareas delegando al DAO las operaciones de consulta, inserción, modificación o eliminación de datos en la fuente de datos, que suele ser una base de datos.

DAO actúa como el nexo adaptador entre un componente (como un controlador o Servlet) y la fuente de datos (Como una base de datos SQLite)

Ventajas

Podemos encontrar un escenario actual donde los datos provienen de diversas fuentes como bases de datos relacionales, no relacionales, archivos, etc. y para cada uno de ellos existe una sintaxis diferente, si se cambiara de base de datos como de un Oracle a un PostgreSQL, la sintaxis del código SQL podría varias drásticamente y modificar las diversas partes de un programa que contengan estas sentencias sería costoso ytomaría mucho tiempo, pero si estas sentencias se encuentran localizadas en una sola área como el DAO, las modificaciones, pruebas e incluso la escalabilidad serías mucho más efectivas.

Los DAO abstraen y encapsulan los accesos a las fuentes de datos de forma que este maneja las conexiones con esa fuente, que podría ser por ejemplo una base de datos MySQL, para obtener los datos y almacenarlos posteriormente.

Usar DAO permite ocultar los procesos empleados en un programa que permiten acceder a la fuente de datos. Además, brinda un gran nivel de adaptación a diversas fuentes de almacenamiento sin afectar a las demás capas.

Nota: en los modelos MVC, MVP, MVVM, entre otros los DAO pertenecen a la capa del modelo (M)

Implementación en JAVA

Teniendo como apoyo un DTO o un OD (aunque no son necesarios, pero sí muy útiles) los DAO deben declarar primero una interfaz (esto dependerá mucho de la manera de implementar este patrón, pero usar interfaces tiene múltiples beneficios), para luego implementarse manteniendo un orden y mejorar la facilidad de emplear pruebas.

Ejemplo

Suponiendo la siguiente tabla y que le hemos creado un DTO (para ver como crear un DTO has clic aquí):
La interfaz "DaoInquilinos.java" se colocará dentro de un paquete llamado "dao", el código para dar un mantenimiento básico a la tabla "inquilinos" será

package dao;
import java.util.List;
import dto.Inquilinos;

public interface DaoInquilinos {
    public List <Inquilinos> inquilinosSel();
    public Inquilinos inquilinosGet(Integer id);
    public String inquilinosIns(Inquilinos inquilino);
    public String inquilinosUpd(Inquilinos inquilino);
    public String inquilinosDel(List<Integer> ids);
    public String getMessage();
}


Ahora debemos implementar cada una de esas funciones en un archivo llamado "DaoInquilinosImpl.java" que colocaremos en un paquete llamado "impl" dentro del paquete "dao", para ello empleamos la palabra reservada "implements" que indica que es la implementación del "DaoInquilinos". El código será:

package dao.impl;

import biblioteca.ConectaBD;
import dao.DaoInquilinos;
import dto.Inquilinos;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class DaoInquilinosImpl implements DaoInquilinos {

    private final ConectaBD conectaDb;
    private String mensaje;

    public DaoInquilinosImpl() {
        this.conectaDb = new ConectaBD();
    }

    @Override
    public List<Inquilinos> inquilinosSel() {
        List<Inquilinos> list = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            list = new ArrayList<>();
            while (rs.next()) {
                Inquilinos inquilinos = new Inquilinos();
                inquilinos.setIdinquilinos(rs.getInt(1));
                inquilinos.setDni(rs.getString(2));
                inquilinos.setNombres(rs.getString(3));
                inquilinos.setPaterno(rs.getString(4));
                inquilinos.setMaterno(rs.getString(5));
                inquilinos.setTelefono(rs.getString(6));
                inquilinos.setCorreo(rs.getString(7));
                inquilinos.setDeuda(rs.getDouble(8));
                inquilinos.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                list.add(inquilinos);
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return list;
    }

    @Override
    public Inquilinos inquilinosGet(Integer id) {
        Inquilinos inquilino = new Inquilinos();
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos WHERE idinquilinos = ?");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    inquilino.setIdinquilinos(rs.getInt(1));
                    inquilino.setDni(rs.getString(2));
                    inquilino.setNombres(rs.getString(3));
                    inquilino.setPaterno(rs.getString(4));
                    inquilino.setMaterno(rs.getString(5));
                    inquilino.setTelefono(rs.getString(6));
                    inquilino.setCorreo(rs.getString(7));
                    inquilino.setDeuda(rs.getDouble(8));
                    inquilino.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                } else {
                    inquilino = null;
                }
            } catch (SQLException e) {
                mensaje = e.getMessage();
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return inquilino;
    }

    @Override
    public String inquilinosIns(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO inquilinos( ")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(") VALUES (?,?,?,?,?,?,?,?) ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "cero filas insertadas";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosDel(List<Integer> ids) {
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM inquilinos WHERE ")
                .append("idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            cn.setAutoCommit(false);
            boolean ok = true;
            for (int id = 0; id < ids.size(); id++) {
                ps.setInt(1, ids.get(id));
                int ctos = ps.executeUpdate();
                if (ctos == 0) {
                    ok = false;
                    mensaje = "ID: " + ids.get(id) + " no existe";
                }
            }
            if (ok) {
                cn.commit();
            } else {
                cn.rollback();
            }
            cn.setAutoCommit(true);
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosUpd(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE inquilinos SET ")
                .append("dni = ?,")
                .append("nombres = ?,")
                .append("paterno = ?,")
                .append("materno = ?,")
                .append("telefono = ?,")
                .append("correo = ?,")
                .append("deuda = ?,")
                .append("fecha_ingreso = ? ")
                .append("WHERE idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            ps.setInt(9, inquilino.getIdinquilinos());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "No se pudo actualizar";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String getMessage() {
        return mensaje;
    }
}

Teniendo la siguiente estructura de carpetas para un proyecto de NetBeans:



domingo, 15 de septiembre de 2019

DTO - Objeto de transferencia de datos

Cuando creamos una aplicación que recibirá peticiones de un cliente, por cada dato que enviemos se realizará una llamada remota, es decir que si tenemos, por ejemplo, una tabla que contiene: código, nombre, apellidos y fecha de nacimiento de un empleado; y nuestro cliente realiza una petición para saber esos datos, se realizará una llamada dato por dato generando 4 llamadas. Para evitar ese consumo de recursos y realizar una comunicación más fluida un DTO empaqueta todos esos datos en un solo objeto reduciendo las llamadas a solo 1.

Los DTO son las clases entidad, estas se pasean por todas las capas cuando se aplica un patrón de diseño de Software como el MVC, MVP o MVVM, se asemejan a las clases en la POO, pero no poseen lógica del negocio.

Características

Teniendo como insumo una tabla de una base de datos como:


Podemos establecer que sus características son:

  • La estructura es idéntica a la de una clase del paradigma de la programación orientada a objetos (POO)
  • Debe cumplir con el encapsulamiento (sus atributos deben tener acceso private) y herencia.
  • Solo debe tener como métodos el constructor (sin parámetros) y los Setter/Getter
  • Como método de buena práctica los atributos deben tener el mismo nombre que los campos de la tabla.


Ejemplo en Java

package dto;

import java.time.LocalDate;

public class Inquilinos {
    private Integer idinquilinos;
    private String dni;
    private String nombres;
    private String paterno;
    private String materno;
    private String telefono;
    private String correo;
    private Double deuda;
    private LocalDate fecha_ingreso;
    public Inquilinos() {
    }
    public Integer getIdinquilinos() {
        return idinquilinos;
    }
    public void setIdinquilinos(Integer idinquilinos) {
        this.idinquilinos = idinquilinos;
    }
    public String getDni() {
        return dni;
    }
    public void setDni(String dni) {
        this.dni = dni;
    }
    public String getNombres() {
        return nombres;
    }
    public void setNombres(String nombres) {
        this.nombres = nombres;
    }
    public String getPaterno() {
        return paterno;
    }
    public void setPaterno(String paterno) {
        this.paterno = paterno;
    }
    public String getMaterno() {
        return materno;
    }
    public void setMaterno(String materno) {
        this.materno = materno;
    }
    public String getTelefono() {
        return telefono;
    }
    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }
    public String getCorreo() {
        return correo;
    }
    public void setCorreo(String correo) {
        this.correo = correo;
    }
    public Double getDeuda() {
        return deuda;
    }
    public void setDeuda(Double deuda) {
        this.deuda = deuda;
    }
    public LocalDate getFecha_ingreso() {
        return fecha_ingreso;
    }
    public void setFecha_ingreso(LocalDate fecha_ingreso) {
        this.fecha_ingreso = fecha_ingreso;
    }
}


Beneficios

Reducción del número de llamadas remotas: mediante una sola llamada donde trae todos los datos contenidos en un solo objeto se logra reducir la cantidad de estas y aumentar la velocidad de respuesta.

Protección del funcionamiento interno del programa: al pasar los datos encapsulados se provee una mayor seguridad ante ingeniería inversa.

Obtener objetos de negocio: en ocasiones podemos encontrar que un DTO es común a muchos negocios o áreas y puede ser considerado un objeto de negocio sirviendo como plantilla para futuras implementaciones a los programadores, desarrolladores, analistas, etc.

Facilidad de pruebas. Si se aplican lenguajes de intercambio como XML o Json, mediante un DTO se puede realizar pruebas con mayor facilidad pára comprobar la integridad de los datos o el funcionamiento de la aplicación.