sábado, 6 de noviembre de 2010

CMT, BMT y métodos callback de SessionSynchronization

Para este ejemplo estoy usando Netbeans 6.9, Ubuntu 10.04, Glassfish y MySQL Database
En este tutorial vamos a crear Transacciones del tipo BMT(Bean Managed Transaction) y del tipo CMT(Container Managed Transaction)
Para esto creamos un proyecto empresarial llamado Transacciones:


Como primer paso vamos a crear una base de datos en mysql llamada DBTransacciones, para esto usamos el comando create database DBTransacciones desde la linea de comando de MySQL.

Una vez creada la base de datos, vamos a agregar la referencia de la libreria de MySQL a nuestro proyecto de Netbeans.
Luego creamos la unidad de persistencia desde Netbeans.
Damos boton derecho sobre el proyecto EJB y seleccionamos New/Other/persistence/Persistence Unit. Le damos el nombre Transacciones-ejbPU, como proveedor de persistencia seleccionamos TopLink y en DataSource seleccionamos new DataSource y creamos un nuevo datasource a DBTransacciones, una vez hecho esto seleccionamos como Table Generation Strategy Drop and Create y damos click en Finish.

Hecho esto vamos a crear tres paquetes uno llamado com.ejemplo.cmt, otro paquete llamado com.ejemplo.bmt y uno llamado com.ejemplo.entity, dentro del proyecto EJB

Hagamos unas puntualizaciones con respecto a CMT y BMT, el primero son transacciones que se ejecutan a nivel del contenedor, con el uso de anotaciones a nivel de los métodos o a nivel de las clases. Mientras que en BMT usamos el tipico begin, commit y rollback en nuestro código.
CMT soporta los siguientes tipos de anotaciones:
REQUIRED: Usado en métodos que necesitan ejecutarse en una transacción pero no necesariamente una nueva transaccion.
REQUIRES_NEW: Si una transacción se deben ejecutar en una nueva transacción
SUPPORTS:Cuando los métodos pueden tener codigo que les permita soportar una transaccion.
MANDATORY: Cuando el método debe ejecutarse obligatoriamente en la transacción.
NOT_SUPPORTED:Para métodos que no deben soportar una transacción.
NEVER:Para métodos que no deben ser llamados dentro de una transaccion.

Para este ejemplo de CMT vamos a crear un método con anotaciones de tipo REQUIRED y otro método del tipo REQUIRES_NEW que haremos que falle.
En com.ejemplo.entity creamos un Entity Class llamado persona. Esta clase tendra las variables miembro nombre, direccion, telefono del tipo String, con sus respectivos getters y setters.
Dentro de com.ejemplo.cmt creamos un session bean del tipo stateless, con interface remota llamado UtilitarioCMT. Agregaremos dos business methods, uno llamado agregarPersona y otro llamado cambiarTelefono.Tambien agregamos una inyeccion de Persistence Context con su respectivo EntityManager.
Agregamos luego de la anotacion de stateless la anotacion @TransactionManagement(TransactionManagementType.CONTAINER), para indicar que vamos a utilizar CMT. Agregamos la anotación @TransactionAttribute(TransactionAttributeType.REQUIRED) antes de la función agregarPersona y la anotación @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) antes de cambiarTelefono. Codificamos agregarPersona para que persista un objeto en la base de datos y cambiarTelefono consultará un registro de la base de datos(dato que no existe) y lo actualizará, entonces fallará y no se ejecutará esta transacción, pero la de agregarPersona si se ejecutará.

Entonces el código quedará de la siguiente manera:

package com.ejemplo.cmt;

import com.ejemplo.entity.Persona;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UtilitarioCMT implements UtilitarioCMTRemote {
@PersistenceContext EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void agregarPersona() {
Persona p=new Persona();
p.setId(1L);
p.setDireccion("Amazonas");
p.setNombre("Juliana");
p.setTelefono("7654321");
em.persist(p);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void cambiarTelefono() {
Persona p=em.find(Persona.class, 12L);
p.setTelefono("1234567");
em.merge(p);
}
}

Luego dejamos el Main del proyecto cliente de la siguiente manera:

package transacciones;

import com.ejemplo.cmt.UtilitarioCMTRemote;
import javax.ejb.EJB;

public class Main {

@EJB private static UtilitarioCMTRemote util;
public static void main(String[] args) {
util.agregarPersona();
util.cambiarTelefono();
}

}

y ejecutamos el proyecto, como veremos aparcerá un error debido a la función cambiarTelefono()

Pero en la base de datos se ha guardado Persona de agregarPersona, debido a que agregarPersona y cambiarTelefono() actuan en dos transacciones diferentes.


Ahora vamos a hacer un ejemplo con BMT, en nuestro paquete com.ejemplo.bmt, creamos un SessionBean del tipo Stateless, con interface remota, llamado UtilitarioBMT. Luego de Stateless agregamos la anotación: @TransactionManagement(TransactionManagementType.BEAN)
y dentro de la clase a mas de la inyeccion de PersistenceContext con su respectivo EntityManager, agregamos una inyección de recurso @Resource UserTransaction ut. Luego creamos la fiuncion crearPersona() y usamos ut.begin() para indicar en donde empieza la transacción y ut.commit() para indicar donde termina la transacción, además de un ut.rollback() en caso de que nos de una excepción y se tengan que deshacer las operaciones hechas. A continuación coloco el respectivo código.

package com.ejemplo.bmt;

import com.ejemplo.entity.Persona;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class UtilitarioBMT implements UtilitarioBMTRemote {
@Resource UserTransaction ut;
@PersistenceContext EntityManager em;
public void crearPersona() {
try {
ut.begin();
Persona p = new Persona();
p.setDireccion("10 de Agosto");
p.setId(2L);
p.setNombre("Adriana");
p.setTelefono("2256776");
em.persist(p);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
} catch (Exception ex1) {
ex1.printStackTrace();
}
ex.printStackTrace();
}
}
}

y nuestro metodo main de la clase Main del proyecto Cliente queda de la siguiente forma:

package transacciones;

import com.ejemplo.bmt.UtilitarioBMTRemote;
import javax.ejb.EJB;

public class Main {
@EJB private static UtilitarioBMTRemote util;
public static void main(String[] args) {
util.crearPersona();

}
}

y arroja la siguiente salida en la Base de Datos:



Vamos a indicar un aspecto extra con respecto a CMT usado en Stateful y es que podemos hacer la llamada a funciones callback antes y después de la ejecución del metodo de la transaccion, para esto vamos a crear el paquete com.ejemplo.cmt.stateful y dentro creamos un SessionBean llamado UtilitarioStateful, de tipo stateful, con interface remota. Dentro colocaremos una función llamada crearPersona y en las interfaces a implementar agregaremos SessionSynchronization, lo cual nos obliga a colocar los métodos afterBegin(),afterCompletion(boolean committed) y beforeCompletion(). Como podemos presumir en base a sus nombres son métodos que se ejecutan antes y después de llamar al metodo de la transacción.El código queda de la siguiente manera:

package com.ejemplo.cmt.stateful;

import com.ejemplo.entity.Persona;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionSynchronization;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateful
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UtilitarioStateful implements UtilitarioStatefulRemote,SessionSynchronization {
@PersistenceContext EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void crearPersona() {
Persona p=new Persona();
p.setId(1L);
p.setDireccion("Naciones Unidas");
p.setNombre("Karla");
p.setTelefono("987654");
em.persist(p);
}

@Override
public void afterBegin() throws EJBException, RemoteException {
System.out.println("Ya empezó");
}

@Override
public void afterCompletion(boolean committed) throws EJBException, RemoteException {
System.out.println("Ya se acabó");
}

@Override
public void beforeCompletion() throws EJBException, RemoteException {
System.out.println("Antes de que se acabe");
}
}

Finalmente cambiamos nuestro metodo main de la clase Main del Proyecto Cliente a:
package transacciones;

import com.ejemplo.cmt.stateful.UtilitarioStateful;
import com.ejemplo.cmt.stateful.UtilitarioStatefulRemote;
import javax.ejb.EJB;

public class Main {
@EJB private static UtilitarioStatefulRemote util;
public static void main(String[] args) {
util.crearPersona();
}
}

y tenemos la salida en la consola de Glassfish:

Creación de relación Varios a Varios.

Para este ejemplo vamos a utilizar mi post llamado Creacion de Unidad de Persistencia con MySQL en Netbeans.
Creamos un nuevo paquete llamado com.ejemplo.entidades.variosvarios. Dentro creamos una Entity Class llamada Pelicula, que tiene una variable miembro llamada título del tipo String y un Set de tipo Productor llamada productores, Este Set debe tener la anotación @ManyToMany(cascade=CascadeType.ALL),junto con sus repectivos getters and setters .Debe tener el siguiente código:

package com.ejemplo.entidades.variosvarios;

import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Pelicula implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String titulo;
@ManyToMany(cascade=CascadeType.ALL)
private Set productores;

public Long getId() {
return id;
}

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

public String getTitulo() {
return titulo;
}

public void setTitulo(String titulo) {
this.titulo = titulo;
}

public Set getProductores() {
return productores;
}

public void setProductores(Set productores) {
this.productores = productores;
}


public Pelicula() {
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Pelicula)) {
return false;
}
Pelicula other = (Pelicula) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
String cadena = "id:" + id + ";titulo:" + titulo;
for (Productor productor:productores) {
cadena += productor.toString();
}
return cadena;
}

}


Luego creamos una Entity Class llamada Productor, que tiene una variable miembro llamada nombre del tipo String y un Set de tipo Pelicula llamada películas, que debe tener un anotación ManyToMany, junto con sus repectivos getters and setters. Con que el código queda de la siguiente manera:

package com.ejemplo.entidades.variosvarios;

import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Productor implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
@ManyToMany(mappedBy = "productores",cascade=CascadeType.ALL)
private Set peliculas;

public Long getId() {
return id;
}

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

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public Set getPeliculas() {
return peliculas;
}

public void setPeliculas(Set peliculas) {
this.peliculas = peliculas;
}



public Productor() {
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Productor)) {
return false;
}
Productor other = (Productor) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
String cadena = "id:" + id + ";nombre:" + nombre;
for (Pelicula pelicula : peliculas) {
cadena += pelicula.toString();
}
return cadena;
}
}

Hecho este código, vamos a crear la clase Utilitario dentro de com.ejemplo.sesion. Ahi hacemos una inyección del persistence Context y usamos un EntityManager para usar la entidad antes creada. Además creamos una funcion llamada relacionVariosVarios, que se encargará de insertar datos (No olvidemos que esta funcion tiene que estar tambien en la interface remota, podriamos usar Insert Code > Add Business Method en Netbeans).Es decir:


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package com.ejemplo.session;

import com.ejemplo.entidades.variosvarios.Pelicula;
import com.ejemplo.entidades.variosvarios.Productor;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
*
* @author santiago
*/
@Stateless
public class Utilitario implements UtilitarioRemote {
@PersistenceContext EntityManager em;

public void relacionVariosVarios() {
Set peliculasJuan=new HashSet();
Set peliculasPedro=new HashSet();
Set peliculasDaniela=new HashSet();
Set peliculasArturo=new HashSet();

Set productoresTitanic=new HashSet();
Set productoresGladiador=new HashSet();
Set productoresTopGun=new HashSet();

Pelicula peliculaTitanic=new Pelicula();
peliculaTitanic.setId(1L);
peliculaTitanic.setTitulo("Titanic");
peliculaTitanic.setProductores(productoresTitanic);

Pelicula peliculaGladiador=new Pelicula();
peliculaGladiador.setId(2L);
peliculaGladiador.setTitulo("Gladiador");
peliculaGladiador.setProductores(productoresGladiador);

Pelicula peliculaTopGun=new Pelicula();
peliculaTopGun.setId(3L);
peliculaTopGun.setTitulo("TopGun");
peliculaTopGun.setProductores(productoresTopGun);

Productor productorJuan=new Productor();
productorJuan.setId(1L);
productorJuan.setNombre("Juan");
productorJuan.setPeliculas(peliculasJuan);

Productor productorPedro=new Productor();
productorPedro.setId(2L);
productorPedro.setNombre("Pedro");
productorPedro.setPeliculas(peliculasPedro);

Productor productorDaniela=new Productor();
productorDaniela.setId(3L);
productorDaniela.setNombre("Daniela");
productorDaniela.setPeliculas(peliculasDaniela);

Productor productorArturo=new Productor();
productorArturo.setId(4L);
productorArturo.setNombre("Arturo");
productorArturo.setPeliculas(peliculasArturo);

productoresTitanic.add(productorJuan);
productoresTitanic.add(productorPedro);
productoresTitanic.add(productorDaniela);

productoresGladiador.add(productorDaniela);
productoresGladiador.add(productorArturo);
productoresGladiador.add(productorPedro);

productoresTopGun.add(productorJuan);
productoresTopGun.add(productorArturo);
productoresTopGun.add(productorDaniela);


em.persist(peliculaTitanic);
em.persist(peliculaGladiador);
em.persist(peliculaTopGun);
}

}

Finalmente el método main del proyecto cliente quedará como:


Relación Uno Varios

Para este ejemplo vamos a utilizar mi post llamado Creacion de Unidad de Persistencia con MySQL en Netbeans.
En esta relación vamos a crear un paquete llamado com.ejemplo.entidades.unovarios



Creamos dentro una Entity Class llamada Producto,


que tendrá las variables miembro:
nombre de tipo String y detalle del tipo Detalle(Clase que ya vamos a crear) que tendra una anotación del tipo ManyToOne con Detalle, generamos sus respectivos getters y setters, junto con un costructor que recibe el id y el nombre. Con lo que la clase nos queda de la siguiente forma:


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package com.ejemplo.entidades.unovarios;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

/**
*
* @author santiago
*/
@Entity
public class Producto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
@ManyToOne
private Detalle detalle;

public Long getId() {
return id;
}

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

public Detalle getDetalle() {
return detalle;
}

public void setDetalle(Detalle detalle) {
this.detalle = detalle;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public Producto(){
}

public Producto(Long id, String nombre) {
this.id = id;
this.nombre = nombre;
}



@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Producto)) {
return false;
}
Producto other = (Producto) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unovarios.Producto[id=" + id + "]";
}

}


Luego creamos otra Entity Class llamada Detalle que tendrá como variables miembro descripción del tipo String y una Lista de tipo Producto llamada productos que tiene una anotación OneToMany. Tambien generamos getters y setters. De tal manera que nos quede de la siguiente manera:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package com.ejemplo.entidades.unovarios;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

/**
*
* @author santiago
*/
@Entity
public class Detalle implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String descripcion;
@OneToMany(mappedBy="detalle",cascade=CascadeType.ALL)
private List productos;

public Long getId() {
return id;
}

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

public String getDescripcion() {
return descripcion;
}

public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}

public List getProductos() {
return productos;
}

public void setProductos(List productos) {
this.productos = productos;
}




@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Detalle)) {
return false;
}
Detalle other = (Detalle) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unovarios.Detalle[id=" + id + "]";
}

}

Hecho este código, vamos a crear la clase Utilitario dentro de com.ejemplo.sesion. Ahí hacemos una inyección del persistence Context y usamos un EntityManager para usar la entidad antes creada. Además creamos una funcion llamada relacionUnoVarios, que se encargará de insertar datos (No olvidemos que esta funcion tiene que estar tambien en la interface remota, podriamos usar Insert Code > Add Business Method en Netbeans). Es decir:


package com.ejemplo.session;

import com.ejemplo.entidades.unovarios.Detalle;
import com.ejemplo.entidades.unovarios.Producto;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class Utilitario implements UtilitarioRemote {
@PersistenceContext EntityManager em;

public void relacionUnoVarios() {
Detalle detalle = new Detalle();
Producto producto1 = new Producto();
producto1.setId(6L);
producto1.setNombre("Cafe");
producto1.setDetalle(detalle);
Producto producto2 = new Producto();
producto2.setId(7L);
producto2.setNombre("Té");
producto2.setDetalle(detalle);
List productos = new ArrayList();
productos.add(producto1);
productos.add(producto2);
detalle.setId(10L);
detalle.setDescripcion("Esta es una prueba de detalles");
detalle.setProductos(productos);
em.persist(detalle);
}

}

El metodo Main tiene el siguiente código:

package relaciones;

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

public class Main {

@EJB private static UtilitarioRemote utilitario;
public static void main(String[] args) {
utilitario.relacionUnoVarios();
}
}

y las consultas a las tablas tienen la siguiente información


Creación de una relacion uno - uno bidireccional

Para este ejemplo vamos a utilizar mi post llamado Creacion de Unidad de Persistencia con MySQL en Netbeans.

Primero creamos un paquete llamado com.ejemplo.session, dentro de este paquete creamos un Session Bean del tipo Stateless con interface Remota llamado Utilitario, que lo usaremos para probar la entidad.


Luego creamos otro paquete llamado com.ejemplo.entidades.unouno.bidireccional, en el proyecto EJB
Dentro de ese paquete vamos a crear un Entity Class


llamado DatosPersonales que tendrá una variable miembro llamada descripcion del tipo String y una variable miembro llamada cliente, del tipo Cliente, con una anotación @OneToOne(cascade=CascadeType.ALL). También creamos los respectivos getters y setters con lo cual el código nos queda de la siguiente manera:


package com.ejemplo.entidades.unouno.bidireccional;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class DatosPersonales implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String descripcion;
@OneToOne(cascade=CascadeType.ALL)
private Cliente cliente;


public Long getId() {
return id;
}

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

public String getDescripcion() {
return descripcion;
}

public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}

public Cliente getCliente() {
return cliente;
}

public void setCliente(Cliente cliente) {
this.cliente = cliente;
}



@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
if (!(object instanceof DatosPersonales)) {
return false;
}
DatosPersonales other = (DatosPersonales) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unouno.unidireccional.DatosPersonales[id=" + id + "]";
}

}

Después de esto creamos otro Entity Class llamado Cliente y le agregamos una variable miembro llamada nombre del tipo String. Tambien agregamos otra variable miembro llamada datosPersonales del tipo DatosPersonales, y sobre la definición de la variable la anotación:@OneToOne(cascade=CascadeType.ALL), esto para indicar la relación unidireccional con DatosPersonales. Tambien creamos los getters y setters de las variable miembro.


Con lo cual el código nos queda de la siguiente manera:


package com.ejemplo.entidades.unouno.bidireccional;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
@OneToOne(cascade=CascadeType.ALL)
private DatosPersonales datosPersonales;

public Long getId() {
return id;
}

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

public DatosPersonales getDatosPersonales() {
return datosPersonales;
}

public void setDatosPersonales(DatosPersonales datosPersonales) {
this.datosPersonales = datosPersonales;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}



@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
if (!(object instanceof Cliente)) {
return false;
}
Cliente other = (Cliente) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unouno.unidireccional.Cliente[id=" + id + "]";
}

}


Hecho este código, vamos a la clase Utilitario de com.ejemplo.sesion.


Ahi hacemos una inyección del persistence Context y usamos un EntityManager para usar la entidad antes creada. Además creamos una funcion llamada relacionUnoUnoBiDireccional, que se encargará de insertar datos en cliente(No olvidemos que esta funcion tiene que estar tambien en la interface remota, podriamos usar Insert Code > Add Business Method en Netbeans). Este objeto debe recibir un objeto del tipo DatosPersonales que tambien debe ser creado. Es decir:

package com.ejemplo.session;

import com.ejemplo.entidades.unouno.bidireccional.Cliente;
import com.ejemplo.entidades.unouno.bidireccional.DatosPersonales;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class Utilitario implements UtilitarioRemote {
@PersistenceContext EntityManager em;
public void relacionUnoUnoBiDireccional() {
DatosPersonales datosPersonales=new DatosPersonales();
Cliente cliente=new Cliente();
datosPersonales.setDescripcion("Ejemplo");
datosPersonales.setId(1L);
datosPersonales.setCliente(cliente);
cliente.setId(1L);
cliente.setNombre("Santiago");
cliente.setDatosPersonales(datosPersonales);
em.persist(cliente); }
}



Luego desde el Main del proyecto cliente, hacemos una inyección de EJB a UtilitarioRemote y llamamos al metodo relacionUnoUnoUniDireccional.

package relaciones;

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

public class Main {

@EJB private static UtilitarioRemote utilitario;
public static void main(String[] args) {
utilitario.relacionUnoUnoBiDireccional();
}
}


Si hacemos una consulta en MySQL veremos que se crearon las tablas Cliente y DatosPersonales.
En cliente se inserto un registro, que guarda referencia a DatosPersonales
En Datos Personales veremos que se inserto un registro con referencia a Cliente



Creación de una relacion uno - uno unidireccional

Para este ejemplo vamos a utilizar mi post llamado Creacion de Unidad de Persistencia con MySQL en Netbeans.

Primero creamos un paquete llamado com.ejemplo.session, dentro de este paquete creamos un Session Bean del tipo Stateless con interface Remota llamado Utilitario, que lo usaremos para probar la entidad.


Luego creamos otro paquete llamado com.ejemplo.entidades.unouno.unidireccional, en el proyecto EJB
Dentro de ese paquete vamos a crear un Entity Class

Lo vamos a llamar DatosPersonales que tendrá una variable miembro llamada descripción del tipo String. Tambien creamos los respectivos getters y setters con lo cual el código nos queda de la siguiente manera:


package com.ejemplo.entidades.unouno.unidireccional;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class DatosPersonales implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String descripcion;

public Long getId() {
return id;
}

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

public String getDescripcion() {
return descripcion;
}

public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}



@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
if (!(object instanceof DatosPersonales)) {
return false;
}
DatosPersonales other = (DatosPersonales) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unouno.unidireccional.DatosPersonales[id=" + id + "]";
}
}

Después de esto creamos otro Entity Class llamado Cliente y le agregamos una variable miembro llamada nombre del tipo String. Tambien agregamos otra variable miembro llamada datosPersonales del tipo DatosPersonales, y sobre la definición de la variable la anotación:@OneToOne(cascade=CascadeType.ALL), esto para indicar la relación unidireccional con DatosPersonales. Tambien creamos los getters y setters de las variable miembro.

Con lo cual el código nos queda de la siguiente manera:


package com.ejemplo.entidades.unouno.unidireccional;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String nombre;
@OneToOne(cascade=CascadeType.ALL)
private DatosPersonales datosPersonales;

public Long getId() {
return id;
}

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

public DatosPersonales getDatosPersonales() {
return datosPersonales;
}

public void setDatosPersonales(DatosPersonales datosPersonales) {
this.datosPersonales = datosPersonales;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}



@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
if (!(object instanceof Cliente)) {
return false;
}
Cliente other = (Cliente) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "com.ejemplo.entidades.unouno.unidireccional.Cliente[id=" + id + "]";
}

}


Hecho este código, vamos a la clase Utilitario de com.ejemplo.sesion.

Ahí hacemos una inyección del persistence Context y usamos un EntityManager para usar la entidad antes creada. Además creamos una funcion llamada relacionUnoUnoUniDireccional, que se encargará de insertar datos en cliente(No olvidemos que esta funcion tiene que estar tambien en la interface remota, podriamos usar Insert Code > Add Business Method en Netbeans).


Este objeto debe recibir un objeto del tipo DatosPersonales que tambien debe ser creado. Es decir:

package com.ejemplo.session;

import com.ejemplo.entidades.unouno.unidireccional.Cliente;
import com.ejemplo.entidades.unouno.unidireccional.DatosPersonales;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class Utilitario implements UtilitarioRemote {
@PersistenceContext EntityManager em;
public void relacionUnoUnoUniDireccional() {
DatosPersonales datosPersonales=new DatosPersonales();
datosPersonales.setDescripcion("Ejemplo");
datosPersonales.setId(1L);
Cliente cliente=new Cliente();
cliente.setId(1L);
cliente.setNombre("Santiago");
cliente.setDatosPersonales(datosPersonales);
em.persist(cliente);
}
}



Luego desde el Main del proyecto cliente, hacemos una inyección de EJB a UtilitarioRemote y llamamos al metodo relacionUnoUnoUniDireccional.

package relaciones;

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

public class Main {

@EJB private static UtilitarioRemote utilitario;
public static void main(String[] args) {
utilitario.relacionUnoUnoUniDireccional();
}
}


Si hacemos una consulta en MySQL veremos que se crearon las tablas Cliente y DatosPersonales.
En cliente se inserto un registro, que guarda referencia a DatosPersonales
En Datos Personales veremos que se inserto un registro, pero sin referencia a Cliente, debido a que es una relación unidireccional


Creando una unidad de Persistencia en Netbeans

Creación de Unidad de Persistencia con MySQL en Netbeans

En este ejemplo estoy usando Netbeans 6.9, Ubuntu 10.04, Glassfish y MySQL Database
Para este ejemplo vamos a crear diferentes relaciones entre clases y por ende entre tablas en la base de datos.
Para esto creamos un proyecto empresarial llamado Relaciones:



Como primer paso vamos a crear una base de datos en mysql llamada DBRelaciones, para esto usamos el comando create database DBRelaciones desde la linea de comando de MySQL.

Una vez creada la base de datos, vamos a agregar la referencia de la libreria de MySQL a nuestro proyecto de Netbeans.

Luego creamos la unidad de persistencia desde Netbeans.
Damos boton derecho sobre el proyecto EJB y seleccionamos New/Other/persistence/Persistence Unit.

Le damos el nombre Relaciones-ejbPU, como proveedor de persistencia seleccionamos TopLink y en DataSource seleccionamos new DataSource y creamos un nuevo datasource a DBRelaciones,



una vez hecho esto seleccionamos como Table Generation Strategy Drop and Create y damos click en Finish