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á...

viernes, 31 de julio de 2015

Mapeo complejo JPA de tablas relacionadas - IV

FICHERO PERSISTENCE.XML

He aquí el fichero Persistence. He utilizado la implementación de Hibernate para JPA.

No tiene más dificultad, si acaso un par de precisiones:
  1. Poned las clases con la ruta correspondiente que hayáis creado en vuestra aplicación; en mi caso las clases están creadas en el paquete main.models. 
  2. Poned en el username el usuario de vuestra base de datos mysql. El password y url idem de idem.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="NominaJPA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <class>main.models.Datosprofesionales</class>
      <class>main.models.Empleado</class>
      <class>main.models.Nomina</class>
      <properties>
          <property name="hibernate.connection.username" value="tu_Usuario"/>
          <property name="hibernate.connection.password" value="tu_password"/>
          <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/nominaDB"/>
          <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
          <property name="hibernate.hbm2ddl.auto" value="update" />
          <!-- Para ver las operaciones sql que se van realizando lo pondríamos en true -->
         <property name="hibernate.show_sql" value="false" />      
      </properties>
   </persistence-unit>
</persistence>


Con esto, tendremos configurada nuestra capa de persistencia. Lo siguiente será crear los ficheros DAO para realizar un adecuado aislamiento entre la capa de persistencia y la de negocio.

Continuará...

jueves, 30 de julio de 2015

Mapeo complejo JPA de tablas relacionadas - III

EXPLICACIÓN DEL MAPEO JPA

Para empezar, decir que es conveniente la anotación @table (name="") porque así nuestras entities pueden tener diferente nombre que las tablas. Soy partidario de esta práctica anotación.
Las columnas han sido mapeadas de la forma habitual, con @Column. Cuando el nombre del atributo de la clase java coincide con el nombre de la columna de la tabla mapeada no es necesario utilizar la etiqueta column. Sin embargo, considero muy útil y conveniente poner siempre el name de la columna mapeada, ya que nos permite modificar en el futuro el atributo sin ocasionar problemas con la base de datos.
Las clases han mapeado el @Id con strategy Identity. Ello es debido a que las tablas se han mapeado con la propiedad AutoIncrement; con esa anotación las tablas gestionan por ellas mismas el valor del id, liberándonos de esa tarea. Los ids han sido creados como long, cuyo equivalente en mysql es BigInt.
El trabajo verdaderamente importante es el mapeo de las relaciones entre las tablas. Como hemos definido antes, el objeto "empleado" está mapeado en dos tablas en las bases de datos, "empleados" y "datosprofesionales". Por lo tanto, ambas tablas deberán estar unidas en una relación @OneToOne bilateral.
Recordemos que, en la relación @OneToOne bilateral establece una relación en la cual cada objeto de una clase tiene relación con uno y solo un objeto de la otra clase, y viceversa. Una de las clases es "dueña" de la relación, lo cual significa que esa clase tendrá una referencia (la id) de la otra clase. Y esa referencia será mapeada en la tabla, en una columna que se añadirá. En la otra clase, la "referenciada", no añadirá ninguna columna a la tabla, pero el objeto tendrá referencia al objeto de la clase "dueña".
El mapeo de las referencias de las otras clases consiste en crear una propiedad del tipo de la clase mapeada, la cual empleará JPA para obtener la referencia id de ese objeto. Ese id será almacenado en el objeto relacionado.
Así pues:
Empleado, la clase "dueña", añade la propiedad private Datosprofesionales profs y guardará la columna en tablas mediante @JoinColumn. El dato guardado en la columna será la id del objeto Datosprofesionales. Y por otro lado, Datosprofesionales, añade la propiedad private Empleado idEmpleado  con mappedBy=profs, lo cual generará una referencia al id del objeto Empleado al cual va unida.
El siguiente mapeo será el de la clase Nominas hacia Empleado y Datosprofesionales. El mapeo de Nominas hacia Empleado es un @ManyToOne bilateral, lo cual significa que un objeto empleado puede tener relación con  varios objetos nomina, mientras que un objeto nomina solo puede tener relación un objeto empleado; y desde ambos deben poder accederse: la nómina debe poder acceder a los datos del empleado, y el empleado debe poder acceder a sus nóminas.
El mapeo de Nominas hacia Datosprofesionales es @ManyToOne unilateral. Cada objeto Nomina tiene relación con un solo objeto Datosprofesionales y puede acceder a esos datos porque tiene referencia. Mientras que un objeto Datosprofesionales no accede directamente a la relación con los objetos Nomina.
La clase Nominas es la clase "dueña" de las relaciones, y por ello mediante @JoinColumn añade dos columnas en su tabla con las cuales referenciada las relaciones con los otros objetos.
Al igual en la relación @OneToOne, la relación @ManyToOne añade propiedades de los objetos referenciados, en nuestro caso private Empleado idEmpleado y private Datosprofesionales idDatosProfesionales; ambas serán referencias id a los objetos correspondientes.
 Por otra parte, en el caso de Datosprofesionales no procede ningún mapeo porque era unilateral. Para nosotros no tiene utilidad que desde datos profesionales podamos acceder a las nóminas.







































En el caso de Empleados, si hay que mapear por la relación es bilateral. Empleados debe mapear @OneToMany, ya que un objeto Empleado puede tener varios objetos Nomina. Sin embargo, en este caso, hablamos de mappedBy. No se creará ninguna columna en la tabla empleados. Pero la referencia a Nomina no será un objeto Nomina, sino un private List<Nomina>nominas; esto es así porque puede haber varios objetos Nomina referenciados. Desde Empleado y mediante el List<Nomina> podremos acceder a todos los objetos Nomina referenciados.
Continuaremos con el fichero persistence.xml ...

lunes, 27 de julio de 2015

Mapeo complejo JPA de tablas relacionadas - II

2.- Mapeo de la tabla Datosprofesionales

@Entity
@Table(name="datosprofesionales")
public class Datosprofesionales implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id_datosprofesionales")
    private String idDatosprofesionales;
    // relacion con la tabla empleado
    @OneToOne(mappedBy="profs")
    private Empleado idEmpleado;
    // informacion sobre el trabajador
    // categoria profesional
    @Column(name="categoria",nullable=false)
    private String categoria;
    // puesto
    @Column(name="tipo",nullable=false)
    private String tipo;
    // informacion sobre el centro de trabajo
    @Column(name="centro",nullable=false)
    private String centro;
    @Column(name="direccion",nullable=false)
    private String direccion;
    @Column(name="localidad",nullable=false)
    private String localidad;

    public Datosprofesionales() {
    }
    public Datosprofesionales(String categoria, String tipo, String centro, String direccion, String localidad) {
            this.categoria = categoria;
            this.tipo = tipo;
            this.centro = centro;
            this.direccion = direccion;
            this.localidad = localidad;
    }
    // AÑADIR GETTERS AND SETTERS
}

3.- Mapeo de la tabla Nomina

@Entity
@Table(name="nominas")
public class Nomina implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id_nominas")
    private long idNominas;
    @ManyToOne
    @JoinColumn(name="id_empleado",nullable=false)
    private Empleado idEmpleado;
    @ManyToOne
    @JoinColumn(name="id_datosprofesionales",nullable=false)
    private Datosprofesionales idDatosProfesionales;
    // periodo (mes) correspondiente a la nomina
    @Column(name="periodo",nullable=false)
    private int periodo;
    // conceptos salariales de remuneracion bruta
    @Column(name="sueldo",nullable=false)
    private float sueldo;
    @Column(name="complemento")
    private float complemento;
    // conceptos retencion fiscal
    @Column(name="porc_irpf",nullable=false)
    private float porcIrpf;
    @Column(name="ret_irpf")
    private float retIrpf;
    // conceptos retencion seg.soc.
    @Column(name="porc_ss",nullable=false)
    private float porcSs;
    @Column(name="ret_ss")
    private float retSs;
    // neto a pagar de la nomina
    @Column(name="neto",nullable=false)
    private float neto;

    public Nomina() {
    }
    public Nomina(Empleado idEmpleado, Datosprofesionales idDatosProfesionales, int periodo, float sueldo, float complemento, float porcIrpf, float retIrpf, float porcSs, float retSs, float neto) {
            this.idEmpleado = idEmpleado;
            this.idDatosProfesionales = idDatosProfesionales;
            this.periodo = periodo;
            this.sueldo = sueldo;
            this.complemento = complemento;
            this.porcIrpf = porcIrpf;
            this.retIrpf = retIrpf;
            this.porcSs = porcSs;
            this.retSs = retSs;
            this.neto = neto;
    }
    @Override
    public String toString() {
            return "Nomina de "+idEmpleado.getNombre()+" - Salario Bruto: "+(getSueldo()+getComplemento())+" - Retenciones: "+(getRetIrpf()+getRetSs())+" - Neto a cobrar: "+getNeto();
    }
            // AÑADIR GETTERS AND SETTERS

}
Continuará...