jueves, 14 de abril de 2011

CRUD Ejemplo - Hibernate - Modelo

Para empezar a trabajar y previa configuración del proyecto es necesario añadir las librerías que se muestran en la siguiente pantalla:



Este ejemplo lo haremos sobre una base de datos postgres en donde crearemos la siguiente tabla:

 CREATE TABLE usuario
(
id serial NOT NULL,
nombres character varying(200) NOT NULL,
apellidos character varying(200) NOT NULL,
correo character varying(200) NOT NULL,
clave character varying(200) NOT NULL,
llave_cambio_clave character varying(200),
fechainactivado timestamp without time zone,
rol integer,
fecha_creacion timestamp without time zone,
bloqueo integer,
CONSTRAINT usuario_pkey PRIMARY KEY (id)
)
Para lo anterior si en el archivo aplication.properties ponemos la siguiente propiedad:
hibernate.hbm2ddl.auto=update con el campo update estamos indicando que al desplegar el war se actualice el esquema de base de datos según el modelo de entidades que definamos.


Ahora creo un DAO (Data Access Object) genérico para trabajar así:

 /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ejemplo.vaadin.dao;
import org.springframework.dao.DataAccessException;
import java.util.List;
/**
* (DAO, Objeto de Acceso a Datos)
* Componente de acceso a datos reutilizable para no reescribir las
* operaciones basicas sobre los objetos del dominio.
* @param <T>
*/
public interface DaoGenerico<T extends Object> {
/**
* Permite cargar una entidad de manera generica
* @param id el id de la entidad a cargar
* @return La entidad cargada
* @throws DataAccessException
*/
public T getById(int id) throws DataAccessException;
/**
* Permite guardar una entidad de manera generica
* @param entidad la entidad a guardar
* @throws DataAccessException
*/
public void guardar(T entidad) throws DataAccessException;
/**
* Permite borrar una entidad de manera generica
* @param entidad La entidad a borrar
* @throws DataAccessException
*/
public void borrar(T entidad) throws DataAccessException;
/**
* Refresca el objeto desde la base de datos aplicando bloqueo para update
* @param entity
*/
public void refrescarBloquear(T entity);
/**
* Lista todas las entidades en el repositorio del tipo definido
* @return El listado de instancias
* @throws DataAccessException
*/
public List<T> listar() throws DataAccessException;
}
 /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ejemplo.vaadin.dao.hibernate;
import com.ejemplo.vaadin.dao.DaoGenerico;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.hibernate.LockMode;
/**
* {@inheritDoc}
*/
public class DaoGenericoImpl<T> implements DaoGenerico<T>
{
protected Class<T> domainClass = extraerClaseDominio();
@Autowired
protected SessionFactory sessionFactory;
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected Class<T> extraerClaseDominio()
{
if( domainClass == null )
{
ParameterizedType thisType = ( ParameterizedType ) getClass().getGenericSuperclass();
domainClass = ( Class ) thisType.getActualTypeArguments()[0];
}
return domainClass;
}
/**
* {@inheritDoc}
*/
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public T getById( int id )
{
return ( T ) sessionFactory.getCurrentSession().get( extraerClaseDominio(), id );
}
/**
* {@inheritDoc}
*/
@Transactional
public void guardar( T entity )
{
sessionFactory.getCurrentSession().saveOrUpdate( entity );
}
/**
* {@inheritDoc}
*/
@Transactional
public void borrar( T entity )
{
sessionFactory.getCurrentSession().delete( entity );
}
/**
* {@inheritDoc}
*/
@Transactional
public void refrescarBloquear( T entity )
{
sessionFactory.getCurrentSession().refresh( entity, LockMode.UPGRADE );
}
/**
* {@inheritDoc}
*/
@Transactional
@SuppressWarnings("unchecked")
public List<T> listar()
{
StringBuilder sb = new StringBuilder( "from " );
sb.append( extraerClaseDominio().getName() );
sb.append( " entity" );
return sessionFactory.getCurrentSession().createQuery( sb.toString() ).list();
}
}

Ahora creo la Entidad Usuario la cual puede ser generada automáticamente con las herramientas provistas por Netbeans la cual le agrega las anotaciones que necesitamos, quedando de la siguiente manera:
 /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ejemplo.vaadin.entidades;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
import java.util.List;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Transient;
/**
* Entidad Usuario que representa la tabla con el mismo nombre en la BD
* @author josorio
*/
@Entity
@Table(name = "usuario")
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "gen_usuario")
@SequenceGenerator(name = "gen_usuario", sequenceName = "usuario_id_seq")
private Integer id;
@Basic(optional = false)
@Column(name = "correo")
private String correo;
@Basic(optional = false)
@Column(name = "clave")
private String clave;
@Basic(optional = false)
@Column(name = "nombres")
private String nombres;
@Basic(optional = false)
@Column(name = "apellidos")
private String apellidos;
@Column(name = "rol")
private Integer rol;
@Column(name = "fechainactivado")
@Temporal(TemporalType.TIMESTAMP)
private Date fechainactivado;
@Column(name = "llave_cambio_clave")
private String llaveCambioClave;
@Column(name = "fecha_creacion")
@Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacion;
//  @Transient
//  @OneToMany(mappedBy = "usuario", fetch = FetchType.LAZY)
//  private List<ValesXpedido> valesXpedidoList;
//  @Transient
//  @OneToMany(mappedBy = "usuario1", fetch = FetchType.LAZY)
//  private List<ValesXpedido> valesXpedidoList1;
@Transient
String nombrecompleto;
public Usuario()
{
}
public Usuario(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCorreo() {
return correo;
}
public void setCorreo(String correo) {
this.correo = correo;
}
public String getClave() {
return clave;
}
public void setClave(String clave) {
this.clave = clave;
}
public String getNombres() {
return nombres;
}
public void setNombres(String nombres) {
this.nombres = nombres;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
public Date getFechainactivado() {
return fechainactivado;
}
public void setFechainactivado(Date fechainactivado) {
this.fechainactivado = fechainactivado;
}
public String getLlaveCambioClave() {
return llaveCambioClave;
}
public void setLlaveCambioClave(String llaveCambioClave) {
this.llaveCambioClave = llaveCambioClave;
}
public Integer getInteger() {
return rol;
}
public void setInteger(Integer rol) {
this.rol = rol;
}
public Date getFechaCreacion() {
return fechaCreacion;
}
public void setFechaCreacion(Date fechaCreacion) {
this.fechaCreacion = fechaCreacion;
}
/**
* Método para asignar al usuario todos los datos del usuario que se entrega como parámetro
* @param usuario
*/
public void copiarDatos(Usuario usuario) {
this.id = usuario.getId();
this.apellidos = usuario.getApellidos();
this.clave = usuario.getClave();
this.correo = usuario.getCorreo();
this.fechainactivado = usuario.getFechainactivado();
this.llaveCambioClave = usuario.getLlaveCambioClave();
this.nombres = usuario.getNombres();
this.rol = usuario.getInteger();
this.fechaCreacion = usuario.getFechaCreacion();
}
public String getNombrecompleto() {
nombrecompleto = nombres+" "+apellidos;
return nombrecompleto;
}
public void setNombrecompleto(String nombrecompleto) {
this.nombrecompleto = nombrecompleto;
}
/**
* Setea en nulo los atributos del objeto. este método se invoca para anular la
* sesión del usuario
*/
public void resetear() {
this.id = -1;
this.rol = null;
this.clave = null;
this.nombres = null;
this.apellidos = null;
this.llaveCambioClave = null;
this.clave = null;
this.correo = null;
}
}

Ahora creo el DAO para gestionar la entidad Usuarios, el cual va a heredar del DAO genérico que creamos arriba y le añadiremos métodos específicos para administrar la entidad:
 /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ejemplo.vaadin.dao;
import com.ejemplo.vaadin.entidades.Usuario;
import java.util.List;
/**
* (DAO, Objeto de Acceso a Datos)
* DAO para la entidad Usuario
* @author arlex
*/
public interface DaoUsuario extends DaoGenerico<Usuario>
{
/**
* Metodo para obtener los usuarios activos (no eliminados) en la Base de datos
* @return un listado con los objetos Usuario recuperados
*/
public List<Usuario> getActivos();
/**
* Obtiene los usuarios el usuario activo al que corresponde el correo suministrado
* @param correo
* @return El usuario al que corresponde el correo suministrado, o null si no se encuentra
*/
public Usuario getActivoByCorreo( String correo );
}
 /*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ejemplo.vaadin.dao.hibernate;
/**
*
* @author josorio
*/
import com.ejemplo.vaadin.dao.DaoUsuario;
import com.ejemplo.vaadin.entidades.Usuario;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Repository
public class DaoUsuarioImpl extends DaoGenericoImpl<Usuario> implements DaoUsuario, Serializable
{
/**
* {@inheritDoc}
*/
public List<Usuario> getActivos()
{
List<Usuario> retorno = null;
try
{
Criteria criteria = sessionFactory.getCurrentSession().createCriteria( Usuario.class );
criteria.add( Restrictions.isNull( "fechainactivado" ) );
criteria.addOrder(Order.asc("nombres"));
retorno = ( List<Usuario> ) criteria.list();
}
catch( Exception e )
{
e.printStackTrace();
}
return retorno;
}
/**
* {@inheritDoc}
*/
public Usuario getActivoByCorreo( String correo )
{
Usuario retorno = null;
try
{
Criteria criteria = sessionFactory.getCurrentSession().createCriteria( Usuario.class );
criteria.add( Restrictions.eq( "correo", correo ) );
criteria.add( Restrictions.isNull( "fechainactivado" ) );
retorno = ( Usuario ) criteria.uniqueResult();
}
catch( Exception e )
{
e.printStackTrace();
}
return retorno;
}
}

Con esto terminamos la creación de las entidades y los DAO para administrar la información de la base de datos usando hibernate.

Siguiente: Controlador
Volver al menú

9 comentarios:

  1. Hola, me parecio muy interesante este articulo.
    Quisiera que me ayudaran a profundizar en el tema "Creación automatica de las anotacion con NETBEANS".
    que opción se puede usar para esto o algun link que me puedan ayudar.

    Gracias !!!

    ResponderEliminar
  2. gracias, en esa parte me refería a crear la entidad con las anotaciones, lo cual se hace siguiendo estos pasos sencillos:
    -click derecho sobre el paquete donde quieres que quede la clase con la entidad.
    -new -> Entity clases from database...
    si no lo encuentras en la lista lo buscas en la opcion other.

    por lo demás es bastante intuitivo estilo programa de instalación de windows

    ResponderEliminar
  3. Hola soy nuevo en spring, pero hay algo que no entiendo..si se supone que netbeans me agrega las librerias de spring..para que hay que agregar jar extras?? y cuales son..todos los que difuran en la lista y dicen spring?
    saludos

    ResponderEliminar
  4. Todas las librerias de spring tienen diferentes funciones spring-core que es el nucleo, spring-mvc, spring-web y varios mas que netbeans no te agrega por defecto

    ResponderEliminar
  5. también es cierto que no todas las agregadas ahí son estrictamente necesarias, podes ir trabajando con lo que te pone netbeans y a medida que se requiera ir agregando las otras.

    ResponderEliminar
  6. gracias por responderme, una consulta mas..veo que las que vos usas tienen el namespace org.springsource...pero las que baje de spring tienen com.springframework..se puede usar igual? o son otras?

    ResponderEliminar
  7. UPDATE: parece que el tema de librerias lo resolvi, pero me da este error:
    org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.ejemplo.vaadin.entidades.Usuario.rol references an unknown entity: java.lang.Integer
    Tenes idea que puede ser?

    ResponderEliminar
  8. Asegúrese de haber importado esta librería en las entidades
    import javax.persistence.*;

    La otra es que revises las configuraciones del applicationContext.xml a ver si mapeo bien las entidades.
    Podes revisar esta url http://vaadinspringhibernate.blogspot.com/2011/04/configuracion-inicial.html

    ResponderEliminar
    Respuestas
    1. Ahora bien el ejemplo original tenia la tabla Usuario y Rol, aca parece que solo esta Usuario por que cambia esto:

      @ManyToOne(fetch = FetchType.EAGER)
      @JoinColumn(name = "rol", nullable = false)
      private Integer rol;

      y lo cambia por:
      @Column(name="rol")
      private Integer rol

      Eliminar