jueves, 16 de junio de 2011

Estrategias en modelado de herencia

Para este ejemplo estoy usando Netbeans 6.9, Ubuntu 10.04, Glassfish V3 y Derby DB

Tenemos tres tipos de estrategias para utilizar herencia en nuestro modelado de objetos:
Modelo de una sola tabla
Modelo de tabla por clase
Modelo de subclase con Join.

Primeramente creamos un nuevo enterprise project al cual llamaremos HerenciaDB.




Luego de esto vamos a crear Session Bean, del tipo Stateless, con interface remota, en el paquete com.ejemplo.session y llamado Utilitario

Ahora vamos a crear una unidad de persistencia en el proyecto EJB llamada puHerencia, con proveedor de persistencia EclipseLink 2.0.
Usaremos el DataSource jdbc/sample y como estrategia de generación de tablas seleccionamos Drop and Create y damos click en Finish.


Una vez hecho esto, vamos a crear el paquete com.ejemplo.entity.empleado.

Dentro de ese paquete, vamos a crear tres clases:
La primera es Empleado(que debe implementar Serializable), que tendra como variables miembro: id y version. Creamos el getter y setter para id y agregamos las respectivas anotaciones, con lo cual el código nos queda como:

package com.ejemplo.entity.empleado;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.Version;

@Entity
@Table(name = "EMP")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Empleado implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Version
protected Integer version;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}
}

Aquí podemos hacer una breve explicación de las anotaciones:
@Entity: Para indicar que es un EJB de Entidad
@Table(name="EMP"): Para indicar con que tabla se relacionará
@Inheritance(strategy=InheritanceType.XXX):Para indicar el tipo de estrategia de herencia que usaremos.
@Id: Indicar que la variable que se escribe a continuación es PK en la DB.
@GeneratedValue(strategy = GenerationType.AUTO): Para indicar que se usará una tabla de secuencia para la generación del PK.
@Version: Para indicar que es un campo que se encargará de llevar la versión del registro.


Una vez creada esta clase, vamos a crear otra llamada EmpleadoTiempoCompleto que extenderá de Empleado y tendra variables miembro y funciones propias, además de implementar Serializable, es decir:

package com.ejemplo.entity.empleado;

import java.io.Serializable;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Entity
@Table(name="FT_EMP")
@DiscriminatorValue("FT")
public class EmpleadoTiempoCompleto extends Empleado implements Serializable {
private static final long serialVersionUID = 1L;
protected Integer salario;

public Integer getSalario() {
return salario;
}

public void setSalario(Integer salario) {
this.salario = salario;
}
}

Luego creamos una clase que se llame EmpleadoTiempoParcial que extenderá de Empleado y tendra variables miembro y funciones propias, además de implementar Serializable, es decir:

package com.ejemplo.entity.empleado;

import java.io.Serializable;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="PT_EMP")
@DiscriminatorValue("PT")
public class EmpleadoTiempoParcial extends Empleado implements Serializable {
protected Float horasTrabajo;

public Float getHorasTrabajo() {
return horasTrabajo;
}

public void setHorasTrabajo(Float horasTrabajo) {
this.horasTrabajo = horasTrabajo;
}
}


Luego de esto, vamos a modificar Utilitario, agregando funcionalidad que nos permita utilizar el Entity Beans creados.
package com.ejemplo.session;

import com.ejemplo.entity.empleado.EmpleadoTiempoCompleto;
import com.ejemplo.entity.empleado.EmpleadoTiempoParcial;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class Utilitario implements UtilitarioRemote {

@PersistenceContext EntityManager em;

public void crearEmpleadoTiempoCompleto() {
EmpleadoTiempoCompleto empleadoTC=new EmpleadoTiempoCompleto();
empleadoTC.setId(1);
empleadoTC.setSalario(1000);
em.persist(empleadoTC);
}

public void crearEmpleadoTiempoParcial() {
EmpleadoTiempoParcial empleadoTP=new EmpleadoTiempoParcial();
empleadoTP.setHorasTrabajo(3.5F);
empleadoTP.setId(2);

em.persist(empleadoTP);
}

}

La interface remota de Utilitario tendrá:
package com.ejemplo.session;

import javax.ejb.Remote;

@Remote
public interface UtilitarioRemote {

public void crearEmpleadoTiempoCompleto();

public void crearEmpleadoTiempoParcial();
}



Finalmente modificamos la clase Main de la siguiente manera:

package herenciadb;

import com.ejemplo.session.UtilitarioRemote;
import javax.ejb.EJB;

public class Main {

@EJB private static UtilitarioRemote utilitario;

public static void main(String[] args) {
utilitario.crearEmpleadoTiempoCompleto();
utilitario.crearEmpleadoTiempoParcial();
}

}

y ejecutamos el proyecto:
Si hacemos una consulta a la base de datos, tenemos:


Donde debemos notar una columna discriminante llamada FT para Empleados Tiempo Completo y PT para empleados tiempo parcial.


Ahora vamos a cambiar la estrategia de generacion. En la clase Empleado cambiamos @Inheritance(strategy=InheritanceType.SINGLE_TABLE) por @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) y ejecutamos nuevamente el proyecto.





Si vemos el schema de la base de datos, veremos dos nuevas tablas: FT_EMP y PT_EMP


Ahora vamos a cambiar la estrategia de generacion. En la clase Empleado cambiamos @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) por @Inheritance(strategy=InheritanceType.JOINED). y en la clase EmpleadoTiempoCompleto luego de @Table(name="FT_EMP") agregamos:@PrimaryKeyJoinColumn(name="FT_EMPID") Esto para colocar un nombre a la columna encargada de manetener la relación. Es por eso que PT_EMPID seguirá conservando el label de ID como PK.





Ejecutamos nuevamente el proyecto.






No hay comentarios:

Publicar un comentario