lunes, 31 de agosto de 2015

Mapeo complejo JPA de tablas relacionadas - VII

Finalizamos el tutorial con los resultados:

RESULTADOS POR PANTALLA


Ejecutamos la aplicación para testear si funciona, y estos son los resultados que debería mostrar la aplicación al ejecutarse:

Lista de empleados
----------------------------
Empleado: Felipe Mendez - DNI: 50999999E - Puesto trabajo: Operario - Centro: Central
Empleado: Andrés Gómez - DNI: 22222222J - Puesto trabajo: Operario - Centro: Almacén
Empleado: Luis Subirana - DNI: 37988123E - Puesto trabajo: Administrativo - Centro: Central

Lista de empleados de la Central
----------------------------
Empleado: Felipe Mendez - DNI: 50999999E - Puesto trabajo: Operario - Centro: Central
Empleado: Luis Subirana - DNI: 37988123E - Puesto trabajo: Administrativo - Centro: Central

Lista de Nominas
----------------------------
Nomina de Felipe Mendez - Periodo 5 - Salario Bruto: 1750.0 - Retenciones: 358.75 - Neto a cobrar: 1391.25
Nomina de Andrés Gómez - Periodo 5 - Salario Bruto: 1450.0 - Retenciones: 333.5 - Neto a cobrar: 1116.5
Nomina de Luis Subirana - Periodo 5 - Salario Bruto: 1700.0 - Retenciones: 391.0 - Neto a cobrar: 1309.0
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25
Nomina de Andrés Gómez - Periodo 6 - Salario Bruto: 2250.0 - Retenciones: 517.5 - Neto a cobrar: 1732.5
Nomina de Luis Subirana - Periodo 6 - Salario Bruto: 2800.0 - Retenciones: 644.0 - Neto a cobrar: 2156.0

Lista de nominas de la Central
----------------------------
Nomina de Felipe Mendez - Periodo 5 - Salario Bruto: 1750.0 - Retenciones: 358.75 - Neto a cobrar: 1391.25
Nomina de Luis Subirana - Periodo 5 - Salario Bruto: 1700.0 - Retenciones: 391.0 - Neto a cobrar: 1309.0
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25
Nomina de Luis Subirana - Periodo 6 - Salario Bruto: 2800.0 - Retenciones: 644.0 - Neto a cobrar: 2156.0

Lista de nominas de un trabajador
----------------------------
Nomina de Felipe Mendez - Periodo 5 - Salario Bruto: 1750.0 - Retenciones: 358.75 - Neto a cobrar: 1391.25
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25

Lista de nominas de un trabajador
----------------------------
Nomina de Felipe Mendez - Periodo 5 - Salario Bruto: 1750.0 - Retenciones: 358.75 - Neto a cobrar: 1391.25
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25

Lista de nominas del mes junio
----------------------------
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25
Nomina de Andrés Gómez - Periodo 6 - Salario Bruto: 2250.0 - Retenciones: 517.5 - Neto a cobrar: 1732.5
Nomina de Luis Subirana - Periodo 6 - Salario Bruto: 2800.0 - Retenciones: 644.0 - Neto a cobrar: 2156.0

Lista de nominas por categoria profesional Operario
----------------------------
Nomina de Felipe Mendez - Periodo 5 - Salario Bruto: 1750.0 - Retenciones: 358.75 - Neto a cobrar: 1391.25
Nomina de Andrés Gómez - Periodo 5 - Salario Bruto: 1450.0 - Retenciones: 333.5 - Neto a cobrar: 1116.5
Nomina de Felipe Mendez - Periodo 6 - Salario Bruto: 2750.0 - Retenciones: 563.75 - Neto a cobrar: 2186.25
Nomina de Andrés Gómez - Periodo 6 - Salario Bruto: 2250.0 - Retenciones: 517.5 - Neto a cobrar: 1732.5


CONCLUSIONES

El mapeo ha sido correcto y ha funcionado de la forma esperada.

Podríamos haber realizado lo mismo y de manera más eficiente con una mejor arquitectura de la base de datos; y también podríamos mejorar nuestra capa de Persistencia. Pero se trata de un programa muy básico en donde hemos realizado el mapeo de datos de un modelo relativamente complejo.

En este ejemplo hemos aprendido a mapear un OneToOne bidireccional, y como influye este mapeo en las tablas de la base de datos. También hemos mapeado un ManyToOne bidireccional y otro unidireccional y sus consecuencias. También hemos accedido y manejado la misma información desde diferentes objetos aprovechándonos de estas propiedades.

Este ejemplo nos ha mostrado algunas de las posibilidades de mapeo  y de manejo de bases de datos con JPA.

¡¡ Hasta pronto, jabatos !!

jueves, 27 de agosto de 2015

Mapeo complejo JPA de tablas relacionadas - VI

Hola de nuevo, jabatos:

EJECUCIÓN Y TESTEO DE LA APLICACIÓN

Llega el momento de comprobar si el mapeo de la base de datos ha sido correcto. Para ello vamos a proceder a crear nuestro fichero main de aplicación JavaSE, al cual vamos a llamar NominaApp.

El diseño de NominaApp será simple. Por un lado crearemos un método que llamaremos generaDatos(). En ese método crearemos y grabaremos los datos de varios trabajadores, junto con las nóminas de varios meses.

La información adicional para la creación de datos sería esta:

  • Las categorias laborales son: peones, auxiliares,oficiales, encargados, administrativos,jefes, directores.
  • Los puestos son: operario, encargado, administrativo, jefe.
  • Los centros de trabajo:

a.       Central - c/albasanz, 24 - Madrid
b.      Almacén - av. de la industria, 4 - Coslada

Por otro lado crearemos el método listaDatos() que se encargará de mostrarnos por pantalla los datos creados anteriormente.

En ambos métodos estaremos testeando el correcto funcionamiento de nuestro mapeo, tanto de nuestras relaciones OneToOne como las relaciones ManyToOne.

He aquí la clase NominaApp:

public class NominaApp {

    private static NominaApp app;
   
    public static void main(String[] args) {
           
            // instanciamos la aplicacion
            app=new NominaApp();
            // creamos los datos
            app.generaDatos();
            // mostramos informacion
            app.listaDatos();
           
            // al terminar cerramos el EntityManagerFactory y cerramos todas la conexiones
            NominaDAO.closeEmf();
    }
   
    private void generaDatos() {

       // PARA TESTEAR ESTA APLICACIÓN VAMOS A CREAR 3 EMPLEADOS CON DISTINTAS CATEGORIAS Y
       // CENTROS DE TRABAJO, Y VAMOS A CREAR DOS NOMINAS DE MESES DISTINTOS POR CADA EMPLEADO.

            NominaDAO nomDAO=new NominaDAO();
           
            // primero los empleados - para ello creamos los datos profesionales y
            // luego los personales
           
            // ***** EMPLEADO 1   
            // datos profesionales
            Datosprofesionales dprof1=new Datosprofesionales("Oficial","Operario","Central","Albasanz, 24","Madrid");
            // datos personales
            Empleado empl1=new Empleado(dprof1,"Felipe Mendez","50999999E","28/034425522/08","Alcala, 522","Madrid","28032",2,1,(float) 12.5,"ESAB00340100001045628945");
           
            if (nomDAO.creaEmpleado(empl1)) {
                    System.out.println("Creado empleado 1");
            } else System.out.println("Error creando empleado");

            // ***** EMPLEADO 2
            // datos profesionales
            Datosprofesionales dprof2=new Datosprofesionales("Auxiliar","Operario","Almacén","Av. de la Industria, 4","Coslada");
            // datos personales
            Empleado empl2=new Empleado(dprof2,"Andrés Gómez","22222222J","28/034567321/07","Miguel Yuste, 5","Madrid","28022",3,0,(float) 15,"ESCD20380105300030056745");
           
            if (nomDAO.creaEmpleado(empl2)) {
                    System.out.println("Creado empleado 2");
            } else System.out.println("Error creando empleado");
           
            // ***** EMPLEADO 3
            // datos profesionales
            Datosprofesionales dprof3=new Datosprofesionales("Administrativo","Administrativo","Central","Albasanz, 24","Madrid");
            // datos personales
            Empleado empl3=new Empleado(dprof3,"Luis Subirana","37988123E","28/018536774/08","Puerto Arlabán, 7","Madrid","28053",3,1,(float) 15,"ESLC01011234013000243511");
           
            if (nomDAO.creaEmpleado(empl3)) {
                    System.out.println("Creado empleado 3");
            } else System.out.println("Error creando empleado");
                   
            // Para crear las nominas, listamos los empleados y grabamos las nominas una a una
            List<Empleado> listaEmpleados=nomDAO.listaEmpleados();
           
            // ***** GRABACION DE LAS NOMINAS DEL MES DE MAYO
            if (listaEmpleados!=null) {
                    for (Empleado emp: listaEmpleados) {
                           int periodo=0; // mes
                           float salario=0; // salario neto
                           float compl=0; //complemento
                           float retIrpf=emp.getRetencion(); //retencion irpf
                           float irpf=(salario+compl)*retIrpf/100;    // cantidad retenida por irpf
                           float retSS=8;          // retencion seguridad social
                           float segsoc=(salario+compl)*retSS/100;    // cantidad retenida por s.s.
                           float neto=salario+compl-irpf-segsoc;  // neto a cobrar en nomina
                           // grabacion de la nomina de mayo
                           if (emp.getNombre().equals("Felipe Mendez")) {
                                   // nomina de Felipe Mendez
                                   // creamos los datos para hacer la nomina del empleado 1 mes mayo
                                   periodo=5; // mes de mayo
                                   salario=1500; // salario neto
                                   compl=250; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           if (emp.getNombre().equals("Andrés Gómez")) {
                                   // nomina de Andrés Gómez
                                   // creamos los datos para hacer la nomina del empleado 2 mes mayo
                                   periodo=5; // mes de mayo
                                   salario=1300; // salario neto
                                   compl=150; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           if (emp.getNombre().equals("Luis Subirana")) {
                                   // nomina de Luis Subirana
                                   // creamos los datos para hacer la nomina del empleado 3 mes mayo
                                   periodo=5; // mes de mayo
                                   salario=1600; // salario neto
                                   compl=100; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           // creamos la nomina y la grabamos
                           Nomina nomina=new Nomina(emp,emp.getProfs(), periodo, salario, compl, retIrpf, irpf, retSS, segsoc, neto);
                           if (nomDAO.creaNomina(nomina)) {
                                   System.out.println("Nomina creada");
                                   System.out.println(nomina.toString());
                           } else System.out.println("Error creando nomina");
                    }
            }
           
           
            // ***** GRABACION DE LAS NOMINAS DEL MES DE JUNIO + PAGA
            if (listaEmpleados!=null) {
                    for (Empleado emp: listaEmpleados) {
                           int periodo=0; // mes
                           float salario=0; // salario neto
                           float compl=0; //complemento
                           float retIrpf=emp.getRetencion(); //retencion irpf
                           float irpf=(salario+compl)*retIrpf/100;     // cantidad retenida por irpf
                           float retSS=8;          // retencion seguridad social
                           float segsoc=(salario+compl)*retSS/100;     // cantidad retenida por s.s.
                           float neto=salario+compl-irpf-segsoc;  // neto a cobrar en nomina
                           // grabacion de la nomina de mayo
                           if (emp.getNombre().equals("Felipe Mendez")) {
                                   // nomina de Felipe Mendez
                                   // creamos los datos para hacer la nomina del empleado 1 mes junio
                                    periodo=6; // mes de junio + paga
                                   salario=2500; // salario neto
                                   compl=250; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           if (emp.getNombre().equals("Andrés Gómez")) {
                                   // nomina de Andrés Gómez
                                   // creamos los datos para hacer la nomina del empleado 2 mes junio
                                   periodo=6; // mes de junio + paga
                                   salario=2100; // salario neto
                                   compl=150; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           if (emp.getNombre().equals("Luis Subirana")) {
                                   // nomina de Luis Subirana
                                   // creamos los datos para hacer la nomina del empleado 3 mes junio
                                   periodo=6; // mes de junio + paga
                                   salario=2700; // salario neto
                                   compl=100; //complemento
                                   retIrpf=emp.getRetencion(); //retencion irpf
                                   irpf=(salario+compl)*retIrpf/100; // cantidad retenida por irpf
                                   retSS=8;                // retencion seguridad social
                                   segsoc=(salario+compl)*retSS/100;  // cantidad retenida por s.s.
                                   neto=salario+compl-irpf-segsoc; // neto a cobrar en nomina
                           }
                           // creamos la nomina y la grabamos
                           Nomina nomina=new Nomina(emp,emp.getProfs(), periodo, salario, compl, retIrpf, irpf, retSS, segsoc, neto);
                           if (nomDAO.creaNomina(nomina)) {
                                   System.out.println("Nomina creada");
                                   System.out.println(nomina.toString());
                           } else System.out.println("Error creando nomina");
                    }
            }
           
    }


    private void listaDatos() {

            // PARA TESTEAR EL ACCESO A DATOS VAMOS A SOLICITAR DIFERENTE INFORMACIÓN A LA APLICACIÓN
            // ACCEDEREMOS DESDE OBJETOS DISTINTOS PARA COMPROBAR QUE LAS RELACIONES ONETOONE,
            // MANYTOONE Y ONETOMANY FUNCIONAN CORRECTAMENTE.
           
            NominaDAO nomDAO=new NominaDAO();
           
            // lista total de empleados
            System.out.println();
            System.out.println("Lista de empleados");
            System.out.println("----------------------------");
            for (Empleado emp:nomDAO.listaEmpleados()) {
                    // aqui se testea el OneToOne
                    System.out.println(emp.toString());
            }
           
            // lista de empleados en la central
            System.out.println();
            System.out.println("Lista de empleados de la Central");
            System.out.println("----------------------------");
            for (Empleado emp:nomDAO.listaEmpleados()) {
                    // aqui se testea el OneToOne
                    if (emp.getProfs().getCentro().equals("Central")) System.out.println(emp.toString());        
            }
           
            // lista de todas las nominas
            System.out.println();
            System.out.println("Lista de Nominas");
            System.out.println("----------------------------");
            for (Nomina nom:nomDAO.listaNominas()) {
                    // aqui se testea el ManyToOne
                    System.out.println(nom.toString());
            }
           
            // lista de las nominas de la central
            System.out.println();
            System.out.println("Lista de nominas de la Central");
            System.out.println("----------------------------");
            for (Nomina nom:nomDAO.listaNominas()) {
                    // aqui se testea el ManyToOne
                    if (nom.getIdDatosProfesionales().getCentro().equals("Central")) System.out.println(nom.toString());
            }
           
            // lista de las nominas de Felipe Mendez
            System.out.println();
            System.out.println("Lista de nominas de un trabajador");
            System.out.println("----------------------------");
            for (Empleado emp:nomDAO.listaEmpleados()) {
                    // aqui se testea el OneToMany
                    if (emp.getNombre().equals("Felipe Mendez")) {
                           for (Nomina nom:emp.getNominas()) {
                                   System.out.println(nom.toString());
                           }
                    }      
            }
            System.out.println();
            System.out.println("Lista de nominas de un trabajador");
            System.out.println("----------------------------");
            for (Nomina nom:nomDAO.listaNominas()) {
                    // REPETIMOS CONSULTA: aqui se testea lo mismo pero con el ManyToOne
                    if (nom.getIdEmpleado().getNombre().equals("Felipe Mendez")) System.out.println(nom.toString());
            }
           
            // lista de las nominas del mes de junio
            System.out.println();
            System.out.println("Lista de nominas del mes junio");
            System.out.println("----------------------------");
            for (Nomina nom:nomDAO.listaNominas()) {
                    // aqui se testea el ManyToOne
                    if (nom.getPeriodo()==6) System.out.println(nom.toString());
            }
           
            // lista de las nominas de la categoria Operario
            System.out.println();
            System.out.println("Lista de nominas por categoria profesional Operario");
            System.out("----------------------------");
            for (Nomina nom:nomDAO.listaNominas()) {
                    // aqui se testea el ManyToOne
                    if (nom.getIdDatosProfesionales().getTipo().equals("Operario"))
                           System.out.println( nom.toString());
            }
    }
}


Continuará...

sábado, 1 de agosto de 2015

Mapeo complejo JPA de tablas relacionadas - V

Hola jabatos:

En este post procederemos a la creación del fichero DAO que manejará la capa de persistencia.

CREACIÓN DEL FICHERO DAO

Para manejar la capa de persistencia emplearemos un fichero DAO conjunto para las clases Empleado y Nomina. La clase Datosprofesionales no va a ser utilizada directamente, sino que sus datos serán accedidos a través de las otra clases.

Lo adecuado sería crear una clase DAO por cada uno de los ficheros models, pero a efectos didácticos de este ejemplo nos será más cómodo manejar una sola clase. Tampoco es adecuado implementar el EntityManagerFactory en una clase DAO, siendo siempre preferible crear una clase propia para crear y manejar ese objeto de acceso a datos. No obstante a efectos prácticos vamos a ignorar deliberadamente esas best-practices.

public class NominaDAO {
public static EntityManagerFactory emf;

public boolean creaEmpleado(Empleado empleado) {
if (empleado==null) return false;
EntityManager em=getSession();
EntityTransaction tx=em.getTransaction();
tx.begin();
try {
em.persist(empleado);
tx.commit();
} catch (Exception ps) {
tx.rollback();
ps.printStackTrace();
return false;
} finally {
if (em!=null) em.close();
}
return true;
}

public List<Empleado> listaEmpleados() {
List<Empleado> empleados=new ArrayList<Empleado>();
EntityManager em=getSession();
EntityTransaction tx=em.getTransaction();
Query q;
tx.begin();
try {
q=em.createQuery("SELECT e FROM Empleado e");
empleados=(List<Empleado>)q.getResultList();
tx.commit();
} catch (Exception ps) {
tx.rollback();
ps.printStackTrace();
return null;
} finally {
if (em!=null) em.close();
}
return empleados;
}

public boolean creaNomina(Nomina nomina) {
if (nomina==null) return false;
EntityManager em=getSession();
EntityTransaction tx=em.getTransaction();
tx.begin();
try {
em.persist(nomina);
tx.commit();
} catch (Exception ps) {
tx.rollback();
ps.printStackTrace();
return false;
} finally {
if (em!=null) em.close();
}
return true;
}

public List<Nomina> listaNominas() {
List<Nomina> nominas=new ArrayList<Nomina>();
EntityManager em=getSession();
EntityTransaction tx=em.getTransaction();
Query q;
tx.begin();
try {
q=em.createQuery("SELECT n FROM Nomina n");
nominas=(List<Nomina>)q.getResultList();
tx.commit();
} catch (Exception ps) {
tx.rollback();
ps.printStackTrace();
return null;
} finally {
if (em!=null) em.close();
}
return nominas;
}

public EntityManager getSession() {
if (emf==null) emf=Persistence.createEntityManagerFactory("NominaJPA");
return emf.createEntityManager();
}
public static void closeEmf() {
emf.close();
}
}

Normalmente, en un fichero DAO, habríamos creado las operaciones CRUD básicas, más las adicionales que vinieran determinadas por la implementación del interface (si lo hubiera) y las que procedieran por las necesidades del negocio. 

En nuestro caso, solo queremos crear objetos, y comprobar si se han creado los objetos mediante un listado. Así pues hemos creado los métodos creaEmpleado(), listaEmpleados, creaNomina() y listaNominas(), cuyo objetivo son bastantes explicitas por su nombre ;-)

Continuará...