Hibernate 3 integracion con Spring



Introducción a Hibernate
Hibernate es un framework de Mapeo Objeto-Relacional (ORM) que facilita el mapeo de atributos entre una base de datos relacional y el modelo de objetos de una aplicación. Para relacionar estos atributos se utilizan archivos de configuración en xml o anotaciones en las clases de entidades, los cuales permiten a la aplicación manipular los datos de la base de datos operando sobre objetos, Hibernate convertirá los datos entre los tipos utilizados por Java y los definidos en SQL, Hibernate genera las sentencias SQL y libera al desarrollador del manejo manual de los datos que resultan de la ejecución de dichas sentencias. También proporciona una alta portabilidad entre todos los motores de base de datos.
Hibernate busca solucionar la diferencia entre los dos modelos de datos en una aplicación, el orientado a objetos (en memoria de la computadora) y el modelo relacional (en la base de datos). Hibernate proporciona también la funcionalidad de crear la base de datos a partir de la información disponible en los archivos de configuración o anotaciones de clases.
Hibernate cuenta con un lenguaje de consultas de datos llamado HQL (Hibernate Query Lenguage) el cual es un lenguaje mas orientado a objetos que relacional. También cuenta con un API para construir consultas conocido como Criteria. También existe la posibilidad de ejecutar instrucciones en SQL.
Integración con Spring
Spring nos provee de una clase llamada HibernateTemplate que provee de muchos métodos expuestos en una interfaz usada por Hibernate la Session adicionado con algunos otros métodos. HibernateTemplate asegura que las instancias de la Session sean correctamente abiertas y cerradas y automáticamente y hacer que nuestras llamadas participen en transacciones. Las instancias de Session en HibernateTemplate son thread-safe y son reusables. Spring también provee de una clase muy util llamada HibernateDaoSupport que nos da la propiedad de tener el SessionFactory y un método getHibernateTemplate para usarlo en subclases, esto nos dará la posibilidad de tener nuestro HibernateTemplate en nuestros DAOs para poder hacer implementaciones simples. El método execute del HibernateTemplate es el principal, el cual nos da acceso directo a la Session.
En la siguiente imagen podemos observar las carpetas de nuestro ejemplo
Para este ejemplo utilizaremos el siguiente modelo de datos
Modelo Relacional (Base de datos)
Modelo Orientado a Objeto
En este ejemplo tenemos el modelo de objetos con las anotaciones que nos proporciona JPA para mapear los datos del modelo relacional con el modelo de objetos. La anotación @Entity indica que se trata de una entidad de JPA, con la anotación @Id indicamos que el atributo al que se hace la anotación es la llave primaria de nuestra tabla, para mapear las columnas utilizamos @Column, si queremos mapear una relación de muchos a uno, como se indica en el diagrama del modelo relacional, utilizamos @ManyToOne, así podemos tener la relación de otra tabla.
ModelType.java
package com.blogspot.appcode.tutorial.hibernate.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "model_type") public class ModelType implements Serializable { private static final long serialVersionUID = -7248230328203761249L; @Id @Column(name = "id") private String id; @Column(name = "name") private String name; @Column(name = "deleted") private Boolean deleted; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getDeleted() { return deleted; } public void setDeleted(Boolean deleted) { this.deleted = deleted; } }
Model.java
package com.blogspot.appcode.tutorial.hibernate.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table; @Entity @Table(name = "model") public class Model implements Serializable { private static final long serialVersionUID = -8463074600122711849L; @Id @Column(name="id") @GeneratedValue(strategy = GenerationType.SEQUENCE) @SequenceGenerator(name = "SEQ_MODEL") private Long id; @Column(name = "name") private String name; @Column(name = "deleted") private Boolean deleted; @ManyToOne @JoinColumn(name = "model_type_id") private ModelType type; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getDeleted() { return deleted; } public void setDeleted(Boolean deleted) { this.deleted = deleted; } public ModelType getType() { return type; } public void setType(ModelType type) { this.type = type; } }
En caso que se quiera hacer la relación base de datos con las clases con archivos de configuración de xml, no será necesario agregar las anotaciones a nuestras clases. Estos archivos xml son un poco mas específicos y dejan a la aplicación sin dependencia con la JPA.
ModelType.hbm.xml
xml version="1.0" encoding="UTF-8"?> DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.blogspot.appcode.tutorial.hibernate.model"> <class name="ModelType" table="model_type"> <id column="id" name="id"> <generator class="assigned"/> id> <property column="name" name="name" /> <property column="deleted" name="deleted" /> class> hibernate-mapping>
Model.hbm.xml
xml version="1.0" encoding="UTF-8"?> DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.blogspot.appcode.tutorial.hibernate.model"> <class name="Model" table="model"> <id column="id" name="id"> <generator class="native"/> id> <property column="name" name="name" /> <property column="deleted" name="deleted" /> <many-to-one column="model_type_id" name="type" /> class> hibernate-mapping>
Ahora crearemos nuestra interfaz del DAO
ModelDao.java
package com.blogspot.appcode.tutorial.hibernate.persistance.impl; import java.util.List; import com.blogspot.appcode.tutorial.hibernate.model.Model; public interface ModelDao { public void save(Model model); public void update(Model model); public void delete(Model model); public List<Model> find(Boolean deleted); public List<Model> find(String name); public List<Model> find(String name,Boolean deleted); }
Ahora crearemos nuestra implementación a partir de la interfaz que definimos, esta implementación se basara en Hibernate, en esta clase heredamos de HibernateDaoSupport para adquirir la funcionalidad de Hibernate gracias a nuestro método getHibernateTemplate. En este ejemplo utilizamos 3 formas de realizar consultas: consultas con HQL, consultas con SQL y consultas utilizando Criteria.
ModelDaoHibernateImpl.java
package com.blogspot.appcode.tutorial.hibernate.persistance.impl; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Restrictions; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.blogspot.appcode.tutorial.hibernate.model.Model; public class ModelDaoHibernateImpl extends HibernateDaoSupport implements ModelDao { @Override public void save(Model model) { getHibernateTemplate().save(model); } @Override public void update(Model model) { getHibernateTemplate().update(model); } @Override public void delete(Model model) { getHibernateTemplate().delete(model); } /* * This method use HQL */ @Override public List<Model> find(final Boolean deleted) { return getHibernateTemplate().execute( new HibernateCallback<List<Model>>() { @Override public List<Model> doInHibernate(Session session) throws HibernateException, SQLException { String hql = "select model from Model model where model.deleted=:deleted"; Query query = session.createQuery(hql); query.setParameter("deleted", deleted); @SuppressWarnings("rawtypes") List resultRawType = query.list(); List<Model> result = new ArrayList<Model>(); for (Object obj : resultRawType) result.add((Model) obj); resultRawType = null; return result; } }); } /* * This method use SQL */ @Override public List<Model> find(final String name) { return getHibernateTemplate().execute( new HibernateCallback<List<Model>>() { @Override public List<Model> doInHibernate(Session session) throws HibernateException, SQLException { String sql = "select * from model where name like ?"; Query query = session.createSQLQuery(sql).addEntity( Model.class); query.setString(0, "%" + name + "%"); @SuppressWarnings("rawtypes") List resultRawType = query.list(); List<Model> result = new ArrayList<Model>(); for (Object obj : resultRawType) result.add((Model) obj); resultRawType = null; return result; } }); } /* * This method use Criteria */ @Override public List<Model> find(final String name, final Boolean deleted) { return getHibernateTemplate().execute( new HibernateCallback<List<Model>>() { @Override public List<Model> doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria = session.createCriteria(Model.class); criteria.add(Restrictions.ilike("name", '%' + name + '%')); criteria.add(Restrictions.eq("deleted", deleted)); @SuppressWarnings("rawtypes") List resultRawType = criteria.list(); List<Model> result = new ArrayList<Model>(); for (Object obj : resultRawType) result.add((Model) obj); resultRawType = null; return result; } }); } }
Ahora lo único que falta es definir nuestros beans para la integración entre Hibernate y Spring, ahora tendremos que definir nuestro Session Factory de Hibernate para el manejo de sesiones. Aquí utilizaremos una clase que contiene Spring en su modulo de ORM para la integración con Hibernate.
Para utilizar las anotaciones nuestro Session Factory quedaría de esta forma:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <bean class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="......." /> <property name="url" value="jdbc:......." /> <property name="username" value="....." /> <property name="password" value="....." /> bean> property> <property name="annotatedClasses"> <list> <value>com.blogspot.appcode.tutorial.hibernate.model.Modelvalue> <value>com.blogspot.appcode.tutorial.hibernate.model.ModelTypevalue> list> property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">......prop> props> property> bean>
En caso de que se quiera utilizar el mapeo por archivos xml utilizaríamos un Session Factory de esta forma:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <bean class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="...." /> <property name="url" value="jdbc:...." /> <property name="username" value="...." /> <property name="password" value="...." /> bean> property> <property name="mappingResources"> <list> <value>com/blogspot/appcode/tutorial/hibernate/persistance/hbm/Model.hbm.xmlvalue> <value>com/blogspot/appcode/tutorial/hibernate/persistance/hbm/ModelType.hbm.xmlvalue> list> property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect....prop> props> property> bean>
Lo único que falta asignar el Session Factory a nuestro DAO para que pueda utilizar la funcionalidad de Hibernate con la administración de sesión que nos proporciona Spring
<bean class="com.blogspot.appcode.tutorial.hibernate.persistance.impl.ModelDaoHibernateImpl"> <property name="sessionFactory" ref="sessionFactory" /> bean>

No hay comentarios:

Publicar un comentario