Hibernate 3
Ramiro González SánchezOctubre del 2006
información confidencial
Contenido
Sesión 1El problema del mapeo Objeto/RelacionalPatrones de Diseño involucradosQuickStart
Sesión 2O/R MappingConsultasPersistencia
Sesión 3TransaccionesHibernate ToolsEvaluación
El problema del mapeo Objeto/Relacional
información confidencial
Partida
UML E/R
Un Modelo de Clases responde necesidades de modelado que no necesariamente satisfacen las reglas de normalización o integridad de un Modelo de Entidad-Relación.
Factura Partida
Factura Partida
Nada impide que unaPartida aparezca en 2Facturas.
información confidencial
UML E/R
Adicionalmente, un Modelo de Clases posee mecanismos que no tienen una contraparte en E/R como: Herencia, Interfases y Relaciones bidireccionales, Multiplicidad muchos a muchos.
Factura
FacturaElectrónica
FacturaImpresa
información confidencial
Labor tediosa
DAO BDValueObjectSQL
ResultSet
get…()ValueObject
ValueObject
Proceso Iterativo:{ get… get… get… }
información confidencial
Problema n + 1
Los joins de tablas no tienen un mapeo “natural”.
Factura
Partida
Partida
Partida
Select *From Factura join Partida
Select *From Factura-- MergeSelect *From Partida
Select *From FacturaFetch {
Select *From Partida
}
Factura
Partida
Partida
Partida
Factura
Partida
Partida
Partida
Factura
Partida
Partida
Partida
Factura
Partida
Partida
Partida
?
información confidencial
Otros problemas
Caching de Objetos: Problema de igualdad.Objetos compartidosObjetos bloqueadosTransacciones sobre objetos
información confidencial
El mundo ideal…
Factura f = new Factura();f.add(new Partida());domainStore.save(f); //insert into Factura; insert into Partida//commit
//
f = query.find(Factura, 12345);// select * from Factura where id = 12345;// select * from Partida where id = 12345;f.removePartida(1);// delete from Partida where …domainStore.save(f);
Patrones de Diseño involucrados
información confidencial
Data Access Object
información confidencial
Domain Store
Clases de Negocio
AdministradorDe
Persistencia
AdministradorDe
Persistencia
BD
Mapeo
QuickStart
información confidencial
Ambiente utilizado para el Curso
Windows XP Professional Edition Service Pack 2J2SE Development Kit v. 1.5.0_04Eclipse SDK 3.1.2MyEclipse IDE v. 4.1.1 GAJBoss 4.0.3 SP1PostgreSQL v. 8.1
Windows XP Professional Edition SP2Windows XP Professional Edition SP2
J2SE Development Kit 1.5.0_06J2SE Development Kit 1.5.0_06
Eclipse SDK 3.1.2Eclipse SDK 3.1.2
MyEclipse 4.1.1 GAMyEclipse 4.1.1 GA
información confidencial
Descargar
ftp://ssdesa01usuario: cursoPassword: curso
información confidencial
Estructura del Ambiente de Desarrollo
MyEclipseMyEclipse
EclipseEclipse
DeploymentServices
Plugins DB Explorer
JBossJBoss
Java Virtual MachineJava Virtual Machine
Java Virtual MachineJava Virtual Machine
PostgreSQL8.1
información confidencial
Verificación de Ambiente
JDKVariable de entorno JAVA_HOME válida%JAVA_HOME%\bin en el PATHEjecutar en línea de comandos java -version
información confidencial
Verificación de Ambiente
MyEclipseVerificar que existe el menú y qué arranca con la correcta versión.
información confidencial
Verificación de Ambiente
JBossLocalizar la carpeta donde está instalado (usualmente C:\Java\jboss-4.0.3SP1)A esta carpeta le llamaremos de ahora en adelante JBOSS_HOMEPosicionarse en línea de comandos en:
%JBOSS_HOME%\binY ejecutar el comando: run.bat
información confidencial
Verificando el Ambiente
PostgreSQL
información confidencial
Arrancar la Base de Datos
información confidencial
Crear Base de Datos
información confidencial
Tabla de Prueba
información confidencial
Nuevo Proyecto
información confidencial
Configuración del Proyecto Java
información confidencial
Finalizando la configuración
información confidencial
Configuración de una conexión
información confidencial
Edición del driver
información confidencial
Agregando el Driver
información confidencial
Driver configurado
información confidencial
Configuración de un Profile de Conexión
información confidencial
Finish…
información confidencial
Abriendo la Conexión
información confidencial
Abrir Conexión…
información confidencial
Habilitando Hibernate en nuestro proyecto
información confidencial
Configuración de Hibernate
información confidencial
Creación de la Configuración
información confidencial
Creación de un SessionFactory
información confidencial
Interfases Hibernate
HibernateHibernate
Session
Transaction
Query
AplicaciónJava
BDjdbc
Cfg(xml)
información confidencial
Elementos Creados
SessionFactory Hibernate.cfg.xml Mappings.hbm.xmlMappings.hbm.xmlMappings.hbm.xml
Session ClasesPersistentes
ClasesPersistentesClases
PersistentesClasesPersistentes
Clase Aplicativa
curr
entS
essi
on()
<<uses>>
<<uses>>
<<uses>>
Query
información confidencial
Configuración de la Conexión en Hibernate
información confidencial
Conexión en Hibernate
información confidencial
Mapping de 1 tabla
información confidencial
ID Generator
información confidencial
Mapping insertado
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="myeclipse.connection.profile">qshibernate</property>
<propertyname="connection.url">jdbc:postgresql://localhost:5432/testHibernate</property>
<property name="connection.username">postgres</property>
<property name="connection.password">notiene</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<mapping resource="mx/com/ids/qshibernate/Mensajes.hbm.xml" />
</session-factory>
</hibernate-configuration>
información confidencial
Código Generado
información confidencial
Log4J
Hibernate utiliza Log4J para enviar sus mensajes de Log.Por lo que se requiere adicionalmente insertar la configuración de Log4j en el classpath:
log4j.logger.org.hibernate.ce=infolog4j.logger.org.hibernate=info
### log HQL query parser activity#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQLlog4j.logger.org.hibernate.SQL=info
### log JDBC bind parameters ####log4j.logger.org.hibernate.type=debug
información confidencial
Obtención de la Conexión
public static Session currentSession() throws HibernateException {Session session = (Session) threadLocal.get();
if (session == null) {if (sessionFactory == null) {
try {cfg.configure(CONFIG_FILE_LOCATION);sessionFactory = cfg.buildSessionFactory();
}catch (Exception e) {
System.err.println("%%%% Error CreatingSessionFactory %%%%");
e.printStackTrace();}
}session = sessionFactory.openSession();threadLocal.set(session);
}return session;
}
información confidencial
Prueba
public static void main(String[] args) {// Step 1 - Create a new entityMensajes message = new Mensajes();// Step 2 - Set message fieldmessage.setTexto("Hello Hibernate, from MyEclipse!");
try {// Step 3 - Get a Hibernate SessionSession session = HSessionFactory.currentSession();// Step 4 - Persist entity to databaseTransaction tx = session.beginTransaction();session.save(message);tx.commit();System.out.println("Save successful.");
} catch (HibernateException e) {System.out.println("Save failed.");
} finally {try {
// Step 5 - close the sessionHSessionFactory.closeSession();
} catch (HibernateException e1) {// do nothing
}}
}
información confidencial
2005-11-10 22:40:49,390 [main] INFO org.hibernate.impl.SessionFactoryImpl -Checking 0 named queries2005-11-10 22:40:49,468 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 42P012005-11-10 22:40:49,468 [main] ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: relation "hibernate_sequence" does not existSave failed.
información confidencial
Especificando el nombre de la secuencia
<id name="id" column="id" type="java.lang.Integer"><generator class="native"><param name="sequence">
mensajes_id_seq</param>
</generator></id>
2005-11-10 22:51:05,328 [main] INFO org.hibernate.impl.SessionFactoryImpl -Checking 0 named queriesSave successful.
información confidencial
Resultado en la base de datos
información confidencial
Prueba 2
public static void main(String[] args) {try {
// Step 1 - Get a Hibernate SessionSession session = HSessionFactory.currentSession();// Step 2 - Crea un queryQuery q = session.createQuery("from Mensajes");
String qSQL = q.getQueryString();System.out.println("Query: " + qSQL);
// Step 3 - Ejecuta el queryList l = q.list();
for (Iterator iter = l.iterator(); iter.hasNext();) {Mensajes element = (Mensajes) iter.next();System.out.println(element.getId() + ":" +
element.getTexto());}
} catch (HibernateException e) {
información confidencial
Prueba 3
public static void main(String[] args) {try {
// Step 1 - Get a Hibernate SessionSession session = HSessionFactory.currentSession();// Step 2 - Crea un query con parametroQuery q = session.createQuery("from Mensajes where id
= :pId");
// Step 3 - Indica el parametroq.setInteger("pId", 1);
// Step 4 - Ejecuta el queryList l = q.list();String qSQL = q.getQueryString();System.out.println("Query: " + qSQL);
for (Iterator iter = l.iterator(); iter.hasNext();) {Mensajes element = (Mensajes) iter.next();System.out.println(element.getId() + ":" +
element.getTexto());}
} catch (HibernateException e) {
O/R Mapping
información confidencial
Modos de Operación
Administrado y No Administrado
HibernateHibernate
Session
Transaction
Query
AplicaciónJava
BDjdbcConnectionPool
HibernateHibernate
Session
Transaction
Query
AplicaciónJava
BDDatasource
TransactionManager
ResourceManager
información confidencial
Propiedades útiles en hibernate.cfg.xml
show_sql = truehibernate.default_schema = ESQUEMAX
información confidencial
Modelo de Pruebas
Factura Partida
Cliente
Producto
Partida
información confidencial
Escritura de POJO’s
Deben Implementar SerializableImplementar un constructor vacío
información confidencial
Escritura de POJO’s
Declarar los métodos set y get de cada propiedad/columna excepto la llave primaria.
información confidencial
Escritura de POJO’s
El tipo de la llave primaria puede ser una clase auxiliar para manejar el caso de llave compuesta.
información confidencial
Escritura de POJO’s
Los campos que representan llaves foráneas deben ser declarados con el tipo de la Clase que representa la entidad foránea.
información confidencial
Asociaciones Bidireccionales
De la Factura al Cliente se puede navegar con la declaración de la columna Cliente en Factura. La operación inversa requiere de declarar un Set de facturas en el cliente.
/** The value of the facturaSet one-to-many association. */private java.util.Set facturaSet;
…public java.util.Set getFacturaSet()
{return this.facturaSet;
}
public void setFacturaSet(java.util.Set facturaSet){
this.facturaSet = facturaSet;}
información confidencial
Cliente.hbm.xml
DTD
Paquete
Clase
PK
Asociación
información confidencial
Factura.hbm.xml
FK
información confidencial
Partida.hbm.xml
LlaveCompuesta
Llave foránea dentro de Llave
Compuesta
información confidencial
Opciones de ID’s
nativeidentitysequence
assigned
Consultas
información confidencial
get()
int clienteId=1;
Cliente cliente = (Cliente) session.get(Cliente.class, new Long(clienteId);
Si el clienteId solicitado no existe, get() regresa null.
información confidencial
Navegando por el Grafo
Una vez cargado un objeto… es posible obtener el resto... siempre y cuando la sesión siga abierta.
Cliente cliente = partida.getFactura().getCliente();
información confidencial
Mediante HQL
Query query = session.createQuery(“from Cliente c where c.email like ‘%ids.com.mx’ ”);List l = query.list();
Esto es idéntico a:
List l = session.find(“from Cliente c where u.email like ‘%ids.com.mx’ ”);
información confidencial
Utilizando SQL Nativo
Query query = session.createQuery(“Select mx.com.ids.qshibernate.Cliente(*)from Cliente where id = :pId”);
List l = query.list();
información confidencial
Query by Criteria
Criteria criteria = session.createCriteria(Cliente.class);criteria.add( Expression.like(“email”, “%ids.com.mx”);criteria.addOrder(Order.asc(“paterno”);
List l = criteria.list();
información confidencial
Query by Example
Cliente clienteX = new Cliente();clientex.setNombre(“Juan”);
Criteria criteria = session.createCriteria(Cliente.class);criteria.add( Example.create(clienteX) );
List l = criteria.list();
información confidencial
Paginación
Utilizando un objeto Query o Criteria
query.setFirstResult(41);query.setMaxResults(20);
información confidencial
Leyendo 1 solo renglón
query.setMaxResult(1);
query.uniqueResult();
información confidencial
Manejo de parámetros
Por nombre(“from Cliente where id = :pId);
Por posición(“from Cliente where nombre = ? and paterno = ?”);La primera posición es 0.
información confidencial
Estrategias de Fetching
Immediate FetchingInmediato (1 por 1)
Lazy FetchingEn el primer acceso (por default)
Eager FetchingEl objeto y sus relaciones
Batch FetchingLectura en lotes (merge)
información confidencial
Estrategia de Acceso
Se puede declarar en el mapeo o durante tiempo de ejecución.
En el mapeo se maneja por Asociación y se tienen 3 parámetros:
lazy = “true” o “false”outer-join = “true” o “false”batch-size = “9”
En una clase solo puede haber una asociación con outer-join=“true”
información confidencial
Profundidad del Fetch
Se debe controlar la profundidad de los joins:hibernate.max_fetch_depth=1,2,3…
Utilizar máximo a 4.
información confidencial
Eager Fetching
Por default, se usa lazy loading…
Para provocar el eager fetching en tiempo de ejecuciónse describe la intención en el query:
from Factura fleft join fetch f.partidaSet
información confidencial
Theta-join
Se utiliza en tablas que no tienen una asociación definida
from User user, LogRecord logwhere user.username = log.username
Esto devuelve pares de los objetos referenciados:
while( i.hasNext() ) {Object[] pair = (Object []) i.next();User user = (User) pair[0];LogRecord log = (LogRecord) pair[1];
}
información confidencial
Report Queries
Tabular
select item.id, item.descriptionorder by item.id
retorna Object[];
Mediante Objeto predefinido
select new Renglon( item.id, item.description )order by item.id
Renglon, debe ser una clase con el constructor apropiado.
información confidencial
Named Queries
En el mapping de la tabla principal:
<sql-query name=“findClientesFacturas”><![CDATA[
select {c.*}, {f.*}from cliente c inner join factura fwhere c.id = f.idcliente
]]><return alias=“c” class=“Cliente” /><return alias=“f” class=“Factura” /></sql-query>
Nota: También funciona para HQL con la etiqueta “query”.
Persistencia
información confidencial
Ciclo de Vida de un Objeto
información confidencial
Creando un objeto persistente
Cliente cliente = new Cliente();
cliente.setNombre(“Juan”);cliente.setPaterno(“Perez”);cliente.setEmail(“[email protected]”);
Session session = QSSessionFactory.currentSession();Transaction tx = session.beginTransaction();
session.save(cliente);tx.commit();session.close();
información confidencial
Actualización de Detached con Update
cliente.setMaterno(“Perez”);
Session session = QSSessionFactory.currentSession();Transaction tx = session.beginTransaction();
session.update(cliente);
cliente.setEmail(“[email protected]”);
tx.commit();session.close();
Cualquier objeto asociado a la base
de datos, se actualiza
automáticamente.
información confidencial
Actualización con Lock
cliente.setMaterno(“Perez”);
Session session = QSSessionFactory.currentSession();Transaction tx = session.beginTransaction();
session.lock(cliente, LockMode.NONE);
cliente.setEmail(“[email protected]”);
tx.commit();session.close();
READUPGRADE
información confidencial
Borrado de un Objeto
session.delete(objeto)
información confidencial
Ejercicio
Instale el ambiente de desarrolloJDKPostgreSQLEclipseMyEclipse
Cree una base de datos con PGAdminIIICorra el script creaTestHibernate.sqlGenere el proyecto configurado para HibernateGenere los mappings de las tablas recién creadasEscriba código que
Inserte 2 clientes nuevosInserte 2 productos nuevosInserte 1 factura a cada cliente con su respectiva partida y referenciando a 1 productoListe los clientes con sus facturas con sus partidas con sus productos
Transacciones
información confidencial
Manejo de Transacciones
La estructura de código estándar y recomendada es la siguiente:
información confidencial
Transacciones dentro del Contenedor J2EE
HibernateHibernate
Session
Transaction
Query
AplicaciónJava
BDDatasource
TransactionManager
ResourceManager
hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactoryhibernate.transaction.manager_lookup_class = <dependiente del Application Server>
información confidencial
JTA Transaction Manager
Borland ESorg.hibernate.transaction.BESTransactionManagerLookup
JRun4org.hibernate.transaction.JRun4TransactionManagerLookup
JOnASorg.hibernate.transaction.JOnASTransactionManagerLookup
JOTMorg.hibernate.transaction.JOTMTransactionManagerLookup
Resinorg.hibernate.transaction.ResinTransactionManagerLookup
Orion/OC4J/OracleASorg.hibernate.transaction.OrionTransactionManagerLookup
WebSphere 6org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
WebSphereorg.hibernate.transaction.WebSphereTransactionManagerLookup
Weblogicorg.hibernate.transaction.WeblogicTransactionManagerLookup
JBossorg.hibernate.transaction.JBossTransactionManagerLookup
Hibernate Tools
información confidencial
Conversión entre Modelos
UML (XMI)UML (XMI)
POJO’sPOJO’s
O/R MappingO/R Mapping
DDLDDL
AndroMDA
Xdoclet
hbm2ddl Middlegen
hbm2java
ReverseEngineering
información confidencial
Instalación de Hibernate Tools
Simplemente se desempaca el paquete que contiene los Hiberneta Tools en el directorio de Eclipse.
información confidencial
Nuevo proyecto Java…
información confidencial
Configuración Proyecto Java
información confidencial
Nuevo Java Package
información confidencial
Nuevo Hibernate Configuration File
información confidencial
Create Hibernate Console Configuration
información confidencial
Verificando
información confidencial
Artifact Generation
información confidencial
Configuración de Artifact Generation
información confidencial
Setup Reverse Engineering
información confidencial
Selección de carpeta y nombre
información confidencial
Include… Exclude…
información confidencial
Configuración final
información confidencial
Confirmación…
información confidencial
Artefactos Generados
información confidencial
HQL Editor
información confidencial
Modelo Relacional
información confidencial
Preguntas…
información confidencial
Referencias
Hibernate in ActionChristian Bauer, Gaving KingManning(disponible en pdf)
www.hibernate.orgDownloads, documentación de referencia.
http://caveatemptor.hibernate.orgAplicación demo de hibernate
Sun J2EE Patterns Cataloghttp://java.sun.com/blueprints/patterns/catalog.html