Ervlets Y JSP Manual De Hibernate

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 159

DownloadErvlets Y JSP Manual De Hibernate
Open PDF In BrowserView PDF
FORMACIÓN EN NUEVAS TECNOLOGÍAS
HIBERNATE AVANZADO
1

ICONO TRAINING

Formación en Nuevas Tecnologías
www.iconotc.com

FORMADOR

Javier Martín
Consultor y Formador en las tecnologías de la
información.

training@iconotc.com
linkedin.com/company/icono-training-consulting

¡Síguenos en las Redes Sociales!

www.iconotc.com

2

Página 1

HIBERNATE AVANZADO
DURACIÓN

14 horas
LUGAR/FECHAS /HORARIO:

Madrid. 11 y 12 de Febrero de 2019. De 9:00 hs a 14:00 hs y de 15:00 hs a 17:00 hs.
CONTENIDOS:

1. Arquitectura (Impartición según nivel de los asistentes)
2.Principales características ((Impartición según nivel de los asistentes)
3.Clases simples
4.Clases con componentes
5.Clases con relaciones unidireccionales
6.Clases con relaciones bidireccionales
7.Clases con jerarquías de herencia
8.El sistema de eventos e interceptadores
www.iconotc.com

3

HIBERNATE AVANZADO
CONTENIDOS (continuación):

9. Lenguaje de consulta
10.Transacciones y concurrencia
11.Uso de anotaciones para definir y manipular la persistencia
12.Uso de Proxies en Hibernate e inicialización perezosa de colecciones y proxies.
13. Optimización de navegación entre entidades (Estrategias para minimizar el número de consultas)
14. Recuperación de lotes.
15. Caches en Hibernate, primer y segundo nivel, Diferentes proveedores de caché de segundo nivel y ventajas de uso de cada
uno, y ejemplos de uso de objetos relacionales (Configurados por regiones en la cache) .

16. Diferencias entre el uso de StandardQueryCache y UpdateTimestampsCache (Y ejemplo práctico de uso) .

www.iconotc.com

4

Página 2

Hibernate

© JAA JMA 2015

http://www.hibernate.org

5

© JAA JMA 2015

INSTALACIÓN

9

Página 3

Con Eclipse
•

Descargar Hibernate:
• http://hibernate.org/orm/downloads/

•

Descargar e instalar JDK:
• http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads2133151.html

•

Descargar y descomprimir Eclipse:

•

Añadir a Eclipse las Hibernate Tools

•

Crear una User Librarie para Hibernate

• https://www.eclipse.org/downloads/
• Help > Eclipse Marketplace: JBoss Tools

•

Descargar y registrar la definición del driver JDBC


Window > Preferences > Data Management > Connectivity > Driver Definition > Add

© JAA JMA 2015

• Window > Preferences > Java > Build Path > User Libraries > New
• Add External JARs: \lib\required

10

Oracle Driver con Maven
•
•

http://www.oracle.com/technetwork/database/features/jdbc/index091264.html
Instalación de Maven:
• Descargar y descomprimir (https://maven.apache.org)
• Añadir al PATH: C:\Program Files\apache-maven\bin
• Comprobar en la consola de comandos: mvn –v

•

Descargar el JDBC Driver de Oracle (ojdbc6.jar):
• https://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html

•

Instalar el artefacto ojdbc en el repositorio local de Maven
• mvn install:install-file -Dfile=Path/to/your/ojdbc6.jar -DgroupId=com.oracle DartifactId=ojdbc6 -Dversion=11.2.0 -Dpackaging=jar

En el fichero pom.xml:

com.oracle
ojdbc6
11.2.0


© JAA JMA 2015

•

11

Página 4

Creación del Proyecto
•
•

New → Maven Proyect
Dependencias en pom.xml

© JAA JMA 2015


1.8
1.8



org.hibernate
hibernate-core
5.4.1.Final


com.oracle
ojdbc6
11.2.0



12

© JAA JMA 2015

INTRODUCCIÓN A HIBERNATE

13

Página 5

Introducción a Hibernate
•

Cuando nos ponemos a desarrollar, en el código final lo que tenemos
que hacer a veces es mucho.

•

Deberemos desarrollar código para:
• Lógica de la aplicación
• Acceso a Base de Datos
• EJB para modularizar las aplicaciones.

•

Deberemos también programar en diferentes Lenguajes:

"La vida es corta, dedique menos tiempo a escribir código para la unión BBDD-Aplicación
JAVA y más tiempo añadiendo nuevas características"

© JAA JMA 2015

• Java (mayoritariamente)
• SQL
• HTML, etc

15

Introducción a Hibernate
Las bases de datos relacionales son indiscutiblemente el centro de la
empresa moderna.

•

Los datos de la empresa se ​basan en entidades que están almacenadas
en ubicaciones de naturaleza relacional. (Base de Datos)

•

Los actuales lenguajes de programación, como Java, ofrecen una visión
intuitiva, orientada a objetos de las entidades de negocios a nivel de
aplicación.

•

Se han realizado mucho intentos para poder combinar ambas
tecnologías (relacionales y orientados a objetos), o para reemplazar uno con el
otro, pero la diferencia entre ambos es muy grande.
© JAA JMA 2015

•

16

Página 6

Discrepancia del Paradigma
•

Cuando trabajamos con diferentes paradigmas (Objetos vs Relacional) la
discrepancia a la hora de unirlos surge a medida que complicamos el
diseño.

•

Cuando disponemos de clases sencillas y relaciones sencillas, no hay
problemas.

Lo anterior no es lo habitual.

© JAA JMA 2015

Pero esto SI:

17

Discrepancia del Paradigma
•

Bauer & King (Bauer, C. & King, G. 2007) presentan una lista de los
problemas de discrepancia en los paradigmas objeto/relacional
• Problemas de granularidad
 Java pueden definir clases con diferentes niveles de granularidad.
– Cuanto más fino las clases de grano (Direcciones), éstas pueden ser embebida en las clases de grano
grueso (Usuario)

 En cambio, el sistema de tipo de la base de datos SQL son limitados y la granularidad se
puede aplicar sólo en dos niveles
– en la tabla (tabla de usuario) y el nivel de la columna (columna de dirección)

• Problemas de subtipos

 Los productos de base de datos SQL en general, no son compatibles con subtipos y herencia
de tablas.

© JAA JMA 2015

 La herencia y el polimorfismo son las características básicas y principales del lenguaje de
programación Java.

18

Página 7

Discrepancia del Paradigma
• Problemas de identidad
 Objetos Java definen dos nociones diferentes de identidad:
- Identidad de objeto (equivalente a la posición de memoria, comprobar con un == b).
- La igualdad como determinado por la aplicación de los métodos equals ().
 La identidad de una fila de base de datos se expresa como la clave primaria.
 Ni equals() ni == es equivalente a la clave principal.

• Problemas de Asociaciones
 El lenguaje Java representa a las asociaciones mediante utilizan referencias a objetos
- Las asociaciones entre objetos son punteros unidireccionales.

© JAA JMA 2015

 Las asociaciones en BBDD están representados mediante el uso de claves externas.
- Todas las asociaciones en una base de datos relacional son bidireccional

19

•

Las siglas ORM significan “Object-Relational mapping” (Mapeo ObjetoRelacional)

•

El ORM es un framework de persistencia de nuestros datos (objetos) a
una base de datos relacional, es decir, código que escribimos para
guardar el valor de nuestras clases en una base de datos relacional.

•

ORM es el nombre dado a las soluciones automatizadas para solucionar
el problema de falta de coincidencia (Objetos-Relacional).

•

Un buen número de sistemas de mapeo objeto-relacional se han
desarrollado a lo largo de los años, pero su efectividad en el mercado ha
sido diversa.





Hibernate
CocoBase
OpenJPA
DataNucleus

TopLink
EclipseLink
Kodo
Amber

© JAA JMA 2015

ORM

20

Página 8

ORM
Descripción

HIBERNATE

Java Community Process empezó a
estandarizar una tecnología de ORM llamada
EBJ 1.0 en el JSR-19.

2001

EJB 2.0. Ampliaron la funcionalidad existentes
hasta ese momento

Gavin King creó Hibernate como alternativa a
EJB x

2003

EJB 2.1 en el JSR-15.
- Ampliaron la funcionalidad existentes hasta
ese momento

Aparece Hibernate2
- Ofrece muchas mejoras significativas con
respecto a la primera versión

2004

Java Data Objects (JDO) es una especificación
de Java object persistence, que amplia la
funcionalidades de EJB2 (Apenas usada)

Nace Hibernate 3.x
- Nuevas características
- arquitectura Interceptor/Callback
- filtros y Anotaciones por el usuario

2006

EJB3 en JSR-220 y JPA en JSR-317

2009-2010

EJB 3.1 en JSR-318

Hibernate 3.5 incluido en JPA
Hibernate 4.0

2011
2012-2013

EJB 3.2 en JSR-345

Hibernate 5.0

- JPA (Java Persistence API) es considerado el estándar de persistencia en Java desarrollada para la plataforma Java EE.
- Hibernate implementa la especificación de JPA

© JAA JMA 2015

AÑO
1999

21

ORM
•

Todo ORM deben de cumplir 4 especificaciones:
1. Un API para realizar operaciones básicas CRUD sobre los objetos de las clases
persistentes. (JDBC)
2. Un lenguaje o API para la especificación de las consultas que hacen referencia a las
clases y propiedades de clases (SQL)
3. Un elemento de ORM para interactuar con objetos transaccionales para realizar
operaciones diversas ( Conexión, validación, optimización, etc) SessionFactory

© JAA JMA 2015

4. Un elemento (fichero) para especificar los metadatos de mapeo (XML)

22

Página 9

Introducción a Hibernate
•

La finalidad de Hibernate es:
• Proporcionar un puente entre los datos relacionales (BBDD) y la Orientación
a Objetos (Java) mediante su modelo de Mapeo Relacional/Objeto ( ORM ) .

•

Para poder desarrollar en Hibernate, deberemos tener conocimientos de:

•

La meta de Hibernate es reducir drásticamente el tiempo y la energía que
gasta el mantenimiento de este entorno, sin perder la potencia y la
flexibilidad asociada a los dos mundos.

•

Hibernate es una solución que satisface el 90% de todos las operaciones
de una aplicación Java enfrentada a su base de datos relacional.

© JAA JMA 2015

 Conocer la lógica de la Aplicación, estructura de clases y objetos
 JDBC
 Conocer Lenguaje de consulta SQL y estructuras de almacenamiento relacional

23

ORM: Hibernate
•

Objetivo de Hibernate:
"Aliviar al desarrollador del 95 % de las tareas de programación
relacionados con la persistencia de datos común."

Hibernate lo resuelve mediante la combinación de clases de Java y
ficheros descriptores XML.

© JAA JMA 2015

•

24

Página 10

ORM: Hibernate
•

Mediante el uso de Hibernate, un desarrollador se libera de escribir
código JDBC y puede centrarse en la presentación y la lógica
empresarial.

•

La utilización de Hibernate y JDBC pueden coexistir sin ningún problema.

•

Hibernate no obliga a seguir unas reglas estrictas ni patrones de diseño.

•

Mediante Hibernate podemos:
Mapear objetos a tablas.
Expresar relaciones de 1 a 1
Expresar relaciones de 1 a N
Expresar relaciones de N a N
© JAA JMA 2015






25

Hibernate: Módulos
•

Hibernate implementa JPA, por lo que dispone de diferentes módulos
para ampliar funcionalidades.
• Hibernate Core
–
–
–
–

Es el servicio BASE para la persistencia.
Dispone de API nativa y ficheros XML para el mapeo de Entidades.
Dispone de un lenguaje de consulta llamado HQL.
Dispone de interfaces de consultas «criteria».

• Hibernate Annotations
– Estas anotaciones permiten especificar de una forma más compacta y sencilla la
información de mapeo de las clases Java.

– (JPA) Es una API se utiliza para acceder a una base de datos en una unidad de trabajo.
– Esta interfaz es similar a la Session en Hibernate.
– Se utiliza para crear y eliminar instancias de entidad persistentes.

© JAA JMA 2015

• Hibernate EntityManager

26

Página 11

Revisión de JDBC. Introducción
•

Casi todas las aplicaciones web son una interfaz para mostrar datos
obtenidos de almacenamientos internos.

•

El almacenamiento mas utilizado son las bases de datos (DB).

•

De hecho, lo que hace que las páginas web sean dinámica es el hecho
de que hay una cantidad significativa de datos detrás de ellos.

•

Una base de datos se compone de:
Unas estructuras de datos
Unas formas de acceso (esquemas)
Y Datos.

• Hoy en día, la mayoría de los SGBD
son relacionales, es decir, sus datos
están organizados en tablas.

© JAA JMA 2015

•
•
•

30

Revisión de JDBC. Introducción
Una estructura habitual de una aplicación Empresarial / J2EE es la
siguiente:

© JAA JMA 2015

•

31

Página 12

Revisión de JDBC. Introducción
•

JDBC proporciona una biblioteca estándar para acceder a bases de
datos relacionales.

•

Mediante el uso de la API de JDBC, puede acceder a una amplia
variedad de bases de datos SQL con exactamente la misma sintaxis de
Java.

•

La API JDBC estandariza:

•

La conexión a bases de datos
La sintaxis para el envío de consultas
La confirmación de las transacciones
La estructura de datos que representa el resultado,

La mayoría de las consultas siguen la sintaxis SQL estándar, y
disponemos de múltiples posibilidades: Cambio de BBDD, Hosts, Puertos, etc

© JAA JMA 2015






32

Pasos Generales JDBC
•

Para realizar una conexión JDBC debemos realizar los siguiente pasos:
1. Cargar el controlador JDBC.


Especificamos el nombre de clase del controlador de base de datos en el método Class.forName.

2. Definir el URL de conexión con BBDD


Una URL de conexión especifica el host del servidor , el puerto y el nombre de base de datos con la que
establecer una conexión.

3. Establecer la conexión


Necesitaremos un usuario y password correctos.

4. Preparar y Ejecutar consulta


Crear, modificar y enviar el objeto Statemente, con un consulta específica.

5. Procesas los resultados
Mediante el objeto ResultSet, se analizan y tratan los resultados
obtenidos de la consulta.

6. Cierre de la conexión

© JAA JMA 2015



33

Página 13

Pasos Generales JDBC
Controladores JDBC
•

Los controladores JDBC son el software que sabe cómo hablar con el servidor de base
de datos real.

•

Para cargar un determinado controlador, deberemos cargar la Clase de Java apropiada
para ese Gestor.
sun.jdbc.odbc.JdbcOdbcDriver (incluido en la API de JDBC de la plataforma J2SE)

 Driver MySQL:

com.mysql.jdbc.Driver

(no incluido)

 Driver DB2:

COM.ibm.db2.jdbc.app.DB2Driver

(no incluido)

 Driver Oracle:

oracle.jdbc.driver.OracleDriver

(no incluido)

Sino están incluidos, deberemos descargar el correspondiente *.jar e insertarlo en el
proyecto.
En uno de estos lugares:
-

Proyect / propiedades / Java Build Path / Libraries / Add external JAR
Directorio : WEB-INF/lib

Si necesitamos los JAR para múltiples aplicaciones →Directorio_de_instalación / common / lib

© JAA JMA 2015

•

 Driver JDBC-ODBC:

34

Pasos Generales JDBC
Controladores JDBC
•

Sintaxis
try {
Class.forName
Class.forName
Class.forName
Class.forName

("connect.microsoft.MicrosoftDriver");
("oracle.jdbc.driver.OracleDriver");
("com.sybase.jdbc.SybDriver");
("com.mysql.jdbc.Driver");

} catch(ClassNotFoundException cnfe) {
System.err.println("Error loading driver: " + cnfe);

WEB.XML

Driver
com.mysql.jdbc.Driver

java.lang.Class.forName(config.getInitParameter("Driver"));

© JAA JMA 2015

}

35

Página 14

Pasos Generales JDBC
URL de Conexión
•

Una vez que haya cargado el controlador JDBC, debe especificar la ubicación del
servidor de base de datos.

•

La URL de referencia utiliza:
 Protocolo : Host : Puerto : Nombre_de_la_BBDD.

•

El formato exacto se define en la documentación que viene con el controlador en
particular

String oracleURL = "jdbc:oracle:thin:@" + host + ":" + port + ":" + dbName;
String sybaseURL = "jdbc:sybase:Tds:" + host + ":" + port + ":" + "?SERVICENAME=" + dbName;
String msAccessURL = "jdbc:odbc:" + dbName;
String MySQLURL = "jdbc:mysql://" + host + ":" + port + ":" + dbName;

© JAA JMA 2015

String host = "dbhost.yourcompany.com";
String dbName = "someName";
int port = 1234;

36

Pasos Generales JDBC
Creando la Conexión
•

Para hacer la conexión, deberemos pasar:
 La dirección URL
 Nombre de usuario de la Base de Datos
 Contraseña del usuario anterior.

•

Utilizaremos el método getConnection de la clase DriverManager,

WEB.XML
:

Usuario
Usuario01
:


String username= config.getInitParameter("Usuario")
String password= config.getInitParameter("Clave")
Connection connection =
DriverManager.getConnection(oracleURL, username, password);

© JAA JMA 2015

String username = "Usuario01";
String password = "1234";
Connection connection = DriverManager.getConnection(oracleURL, username, password);

37

Página 15

Pasos Generales JDBC
•

Ejemplo
public static void main(String args[]) {
String usuario = "system";
String password = "oracle";

String driver = "oracle.jdbc.driver.OracleDriver";
String ulrjdbc = "jdbc:oracle:thin:" + usuario + "/" + password + "@" + host + ":" +
puerto + ":" + sid;
try {
Class.forName(driver).newInstance();
Connection conexion= DriverManager.getConnection(ulrjdbc);
// Ya tenemos el objeto connection creado
System.out.println(“Nos hemos conectado correctamente a la Base de Datos”);
} catch (Exception e) { e.printStackTrace(); }
}

© JAA JMA 2015

String host = "localhost"; // también puede ser una ip como "192.168.1.14"
String puerto = "1521";
String sid = "xe";

38

Pasos Generales JDBC
Preparar y Ejecutar Consulta
•

Para preparar y ejecutar una consulta en la Base de Datos necesitamos crear un objeto
Statement.

•

Sintaxis
Statement st = connection.createStatement();

•

La mayoría, pero no todos, los controladores de base de datos permiten tener múltiples
objetos Statement abiertos la misma conexión.

•

Ahora utilizaremos este objeto para insertarle una Consulta SQL y ejecutarla

ResultSet resultSet = st.executeQuery (query);
Int filas = st.executeUpdate (query);
Array[] valores = st.executeBatch(query);

SELECT
DML
SQL Multiples

© JAA JMA 2015

String query = "SELECT col1, col2, col3 FROM Tabla";

40

Página 16

Pasos Generales JDBC
Procesar los resultados
•

Para procesar los resultamos utilizamos el objeto ResultSet, para recorrer todos los
resultados devueltos (tipo cursor)

•

ResultSet proporciona diversos métodos getXXX que devuelven el resultado en una
variedad de diferentes tipos de Java.
 getInt
 getString
 getDate

•

→
→
→

número entero
Cadena de texto
Fechas

Ahora utilizaremos este objeto para insertarle una Consulta SQL y ejecutarla

Valor_c1 – 1

Valor_c2 – 1

Valor_nombre – 1

Valor_apellido – 1

Valor_c1 – 2

Valor_c2 – 2

Valor_nombre – 2

Valor_apellido – 2

Valor_c1 – 3

Valor_c2 – 3

Valor_nombre – 3

Valor_apellido – 3

© JAA JMA 2015

while(resultSet.next()) {
System.out.println ( resultSet.getString(1) + " " + resultSet.getString(2) + " " +
resultSet.getString("nombre") + " “ + resultSet.getString("apellido") );
}

41

Pasos Generales JDBC
Cerrar la conexión
•

Cuando cerramos la conexión, todos los objetos del tipo Statement y ResultSet son
eliminados.

•

S queremos volver a comunicarnos con la BBDD después de haber realizado el cierre
de una conexión, deberemos realizar todo el proceso completo de nuevo.

•

Sintaxis

© JAA JMA 2015

connection.close();

42

Página 17

© JAA JMA 2015

OPERACIONES BÁSICAS CON
HIBERNATE

44

•

La forma más sencilla de comenzar con Hibernate es trabajar con
una simple clase de Java y una única tabla en Base de Datos.

•

Elementos básicos:
•

Estructura de datos disponible para su utilización ( Base de Datos, Tablas, etc).

•

(opcional) Java Bean para la realización de peticiones o consultas.

•

Fichero de mapeado XML para el acceso a la BBDD (tabla.hbm.xml)

•

Fichero XML de configuración de Hibernate (hibernate.cfg.xml)

•

Clase Principal de Java para realizar las peticiones ( a través de Java Beans )

Para la explicación utilizaremos la TABLA PROFESOR creada por el script_profesor.sql

© JAA JMA 2015

Elementos Básicos de Hibernate

47

Página 18

Elementos Básicos de Hibernate
•

Elementos básicos:
1. Estructura de datos disponible para su utilización ( Base de Datos, Tablas, etc).

© JAA JMA 2015

Utilizaremos la Tabla PROFESOR creada por el script_profesor.sql, con la
siguiente estructura.

48

Elementos Básicos de Hibernate
•

Elementos básicos:
2.- (opcional) Java Bean para la realización de peticiones o consultas.
•

La clase Java que vamos a utilizar como entidad o documento para las
operaciones DML/DQL, deberá seguir los estándar de creación de Java Beans.
 Debe ser publica (no puede ser estar anidada ni final o tener miembros finales)
 Deben tener un constructor público sin ningún tipo de argumentos.
 Para cada propiedad que queramos persistir debe haber un método get/set asociado.
 Debe tener una clave primaria
 Debería sobrescribir los métodos equals y hashCode

•

Habitualmente, el nombre de la clase de Java es igual a la tabla que vamos hacer
referencia.

© JAA JMA 2015

 Opcionalmente (para utilizar de forma remota), implementar el interfaz Serializable

50

Página 19

Elementos Básicos de Hibernate
•

Elementos básicos:
2.- (opcional) Java Bean para la realización de peticiones o consultas.
→ new Package
→ new Class → Profesor

Fichero Profesor.java
public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
public Profesor(){ }
public Profesor(int id, String nombre, String ape1, String ape2) {
this.id = id;
this.nombre = nombre;
this.ape1 = ape1;
this.ape2 = ape2;
}

public String getNombre() { return nombre; }
public void setNombre(String nombre) { this.nombre = nombre; }
public String getApe1() { return ape1; }
public void setApe1(String ape1) { this.ape1 = ape1; }
public String getApe2() { return ape2; }

public void setId(int id) { this.id = id; }
public void setApe2(String ape2) { this.ape2 = ape2; }
}

© JAA JMA 2015

public int getId() { return id; }

51

Elementos Básicos de Hibernate
•

Elementos básicos:
3.- Fichero de mapeado XML para el acceso a la BBDD (Profesor.hbm.xml)
•

Para cada clase que queremos persistir se creará un fichero .hbm.xml con la
información que permitirá mapear la clase a una base de datos relacional.

•

Este fichero estará en el mismo paquete que la clase a persistir.

•

En nuestro caso, si queremos persistir la clase Profesor deberemos crear el
fichero Profesor.hbm.xml en el mismo paquete que la clase Java.

•

El fichero tiene una configuración XML

© JAA JMA 2015

NEW→ Others → Find Hibernate →

52

Página 20

Elementos Básicos de Hibernate
•

Elementos básicos:
3.- Fichero de mapeado XML para el acceso a la BBDD (Profesor.hbm.xml)


Declaración de un fichero XML y
la validación de fichero de Hibernate




NODO RAIZ






Mapeo de la Clase
Name= Paquete.Clase
Table= Tabla de la BBDD
Propiedad de la clase que es la clave primaria
Column=Columna de la BBDD asociada
Name= Nombre de la propiedad JAVA
Type= Tipo de Java




Declarar de las demás propiedades, para su utilización.
Si no las declaramos no se leerán/guardarán en la BBDD.
Name= Nombre de la propiead JAVA
Column= Columna de la BBDD Asociada

© JAA JMA 2015



53

Elementos Básicos de Hibernate
•

Elementos básicos:
4.- Fichero XML de configuración de Hibernate (hibernate.cfg.xml)
•

Para poder realizar la conexión con la BBDD, necesitamos un fichero donde
aparezca dicha información fichero hibernate.cfg.xml .

•

Este fichero deberemos guardarlo en el paquete raíz de nuestras clases Java, es
decir fuera de cualquier paquete.

•

La información que contiene es la siguiente:
 Propiedades de configuración.
– Driver, usuario, password, Lenguaje de comunicación, etc

•

Su ubicación debe de ser en los directorios web-inf o src

© JAA JMA 2015

 Las clases que se quieren mapear.

54

Página 21

Elementos Básicos de Hibernate
•

Elementos básicos:
4.- Fichero XML de configuración de Hibernate (hibernate.cfg.xml)

© JAA JMA 2015

NEW→ Others → Find Hibernate →

55

Elementos Básicos de Hibernate
•

Elementos básicos:
4.- Fichero XML de configuración de Hibernate (hibernate.cfg.xml)


RAIZ Documento

com.mysql.jdbc.Driver
jdbc:mysql://localhost/hibernate1
hibernate1
hibernate1
org.hibernate.dialect.MySQL5Dialect
true





contienen propiedades de
la configuración de conexión:
- driver, url, usuario, clave

Fichero .hbm.xml asociada a la clase
que queremos persistir.
contiene el nombre de la clase que
queremos persistir.

© JAA JMA 2015




Declaración de un fichero XML y
la validación de fichero de Hibernate

56

Página 22





false
oracle.jdbc.driver.OracleDriver
jdbc:oracle:thin:@localhost:1521:xe
alumno
alumno
ALUMNO
org.hibernate.dialect.Oracle10gDialect
false
false



© JAA JMA 2015

Elementos Básicos de Hibernate

57

Elementos Básicos de Hibernate
Descripción

connection.driver_class

- Driver de conexión con la BBDD

connection.url

- La URL de conexión a la base de datos tal y como se usa en JDBC

connection.username

- Usuario de la BBDD

connection.password

- Clave del usuario en la BBDD

dialect

- Especificación del Lenguaje SQL que usará Hbernate contra la BBDD.
- Parámetro opcional, Hibernate puede "Averiguarlo"

hibernate.show_sql

- Indica si se mostrará por la consola la orden SQL que Hibernate contra
la base de datos.
- Su posibles valores son true o false. Esta propiedad es muy útil mientras
programamos ya que nos ayudará a entender cómo está funcionando
Hibernate

connection.datasource

- Indica el nombre del DataSource con el que se conectará Hibernate a la
base de datos.
- Esta propiedad se usa en aplicaciones Web ya que los datos de la
conexión se definen en el servidor de aplicaciones y se accede a la base
de datos a través del DataSource

© JAA JMA 2015

Propiedad

58

Página 23

Elementos Básicos de Hibernate
•

Elementos básicos:
4.- Fichero XML de configuración de Hibernate (hibernate.cfg.xml)
TAG 


Para indicar que clase queremos mapear y contra qué tabla utilizamos el TAG




Lo habitual es utilizar el fichero de mapeo utilizado anteriormente (tabla.hbm.xml)
utilizando el atributo resource:




Para mapear la clase utilizamos el atributo class:

© JAA JMA 2015



59

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java para realizar las peticiones
•

Para poder dar funcionalidad a todo esto, necesitaremos 3 elementos:

•

La clase Session contiene métodos para leer, guardar o borrar entidades sobre
la base de datos.

•

La Clase SessionFactory nos permite crear un objeto Session para toda la
comunicación.

•

La Clase Configuration nos permite leer el fichero de configuración de Hibernate
hibernate.cfg.xml

© JAA JMA 2015

 Objeto Session de la Clase org.hibernate.Session.
 Objeto SessionFactory de la Clase org.hibernate.SessionFactory.
 Objeto Configuration de la Clase org.hibernate.cfg.Confguration.

60

Página 24

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Creación del Objeto SessionFactory
La primera operación a realizar es la creación del Objeto SessiónFactory.

•

Este objeto es de creación única por aplicación y lo podremos reutilizar en todas las
llamadas que necesitemos.

•

Hay 2 posibilidades de creación (como ahora veremos), una < Hibernate 4 y otra post
Hibernate 4 y superiores.

© JAA JMA 2015

•

61

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Creación del Objeto SessionFactory
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
SessionFactory sessionFactory;
Configuration configuration = new Configuration();
configuration.configure();

Deprecated

sessionFactory = configuration.buildSessionFactory();

:
session.close();

© JAA JMA 2015

ServiceRegistry serviceRegistry = new
ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);

62

Página 25

HibernateUtil
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();

public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}

© JAA JMA 2015

private static SessionFactory buildSessionFactory() {
// A SessionFactory is set up once for an application!
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // configures settings from hibernate.cfg.xml
.build();
try {
return new MetadataSources(registry ).buildMetadata().buildSessionFactory();
}
catch (Exception ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

63

HibernateUtil (Ver. 5.x)
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();

public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}

© JAA JMA 2015

private static SessionFactory buildSessionFactory() {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // configures settings from hibernate.cfg.xml (JndiException: name="")
.build();
try {
return new MetadataSources( registry ).buildMetadata().buildSessionFactory();
}
catch (Exception ex) {
// The registry would be destroyed by the SessionFactory, but we had trouble building
// the SessionFactory so destroy it manually.
StandardServiceRegistryBuilder.destroy( registry );
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

64

Página 26

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Creación del Objeto Session
•

Una vez creado el Objeto SessionFactory podemos obtener la Session para trabajar
con Hibernate.

•

Es tan sencillo como llamar al método openSession() de sessionFactory.
Session session = HibernateUtil.getSessionFactory().openSession();

•

Una vez obtenida la sesión trabajaremos con Hibernate persistiendo las clases y una
vez finalizado se deberá cerrar la sesión con el método close():

© JAA JMA 2015

session.close();

65

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Creación del Objeto SessionFactory
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
SessionFactory sessionFactory;
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry serviceRegistry = new
ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);

:
session.close();

© JAA JMA 2015

Session session = sessionFactory.openSession();

66

Página 27

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Transacciones
•
•

Para poder trabajar con la Base de Datos, necesitamos utilizar transacciones.
En Hibernate disponemos de 4 operaciones básicas sobre transacciones:
 Creación de una transacción
session.beginTransaction();

 Validación de la transacción actual.
session.getTransaction().commit();

 Rollback de la transacción actual.
session.getTransaction().rollback();

session.closeTransaction();

© JAA JMA 2015

 Cierre de la transacción actual.

67

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Transacciones
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
SessionFactory sessionFactory;
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry serviceRegistry = new
ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();

:
session.close();

© JAA JMA 2015

Session.beginTransaction();

68

Página 28

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
Entendemos por Operaciones CRUD las operaciones básicas que se realizan en toda
tabla:





•

Create:
Read:
Update:
Delete:

Insertar un nuevo objeto en la base de datos.
Leer los datos de un objeto de la base de datos.
Actualizar los datos de un objeto de la base de datos.
Borrar los datos de un objeto de la base de datos.

Cada una de estas operaciones tiene asignado un método del objeto Session para su
realización.






Create:
Read:
Update:
Delete:
Actualizar

session.save(…..);
session.get(….);
session.update(…..);
session.delete(….);
o Insertar

© JAA JMA 2015

•

69

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Lectura
 Utilizaremos el método get (Class, ID) para obtener información del elemento guardado en la
Tabla y que tenga ese número de Identificación.
 Este método permite SOLO leer un UNICO Objeto
 Necesitamos hacer un CAST para identificar el tipo de objeto.

Profesor profesor=(Profesor) session.get(Profesor.class, 101);
System.out.println(profesor.getNombre());
session.close()

SI error parsing JNDI hibernate name
Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

:
Session session = sessionFactory.openSession();
session.beginTransaction();

70

Página 29

Lenguajes de consultas
•

En Hibernate existen 3 maneras para realizar consultas.
•

HQL (Hibernate Query Lenguage)
session.createQuery("from Category c where c.name like 'Laptop%'");
entityManager.createQuery("select c from Category c where c.name like 'Laptop%‘ ");

•

CRITERIA API
session.createCriteria(Category.class).add( Restrictions.like("name", "Laptop%") )

•

Direct SQL

© JAA JMA 2015

session.createSQLQuery("select {c.*} from CATEGORY {c} where NAME like 'Laptop%‘
").addEntity("c", Category.class);

71

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Lectura múltiple (consulta)
 La consultas se crean con la sesión.
 Se materializan con el método list()

:
Session session = sessionFactory.openSession();
Query consulta = session.createQuery("from Profesor");
List rslt = consulta.list();
for(Profesor profesor : rslt){
System.out.println(profesor.getNombre());
}
SI error parsing JNDI hibernate name
session.close()
Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

 La colección resultante estará vacía si la consulta no produce resultados.

72

Página 30

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Creación / Inserción
 Utilizaremos el método save (objeto) con el elemento a guardar.
 El objeto será/deberá de ser igual a un registro de la tabla que tengamos mapeado.
 Siempre deberemos validar la transacción antes de su finalización.

:
Profesor profesor=new Profesor(101, “Adriana", “Sanchez", “Meneses"); //Creamos el objeto
Session session = sessionFactory.openSession();
session.beginTransaction();

SI error parsing JNDI hibernate name

session.getTransaction().commit();
session.close()

Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

session.save(profesor);

73

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Actualización
 Utilizaremos el método update(Object objeto) con el objeto a actualizar en la Base de Datos.
 Este método permite SOLO actualizar un UNICO Objeto

SI error parsing JNDI hibernate name
Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

:
Session session = sessionFactory.openSession();
session.beginTransaction();
Profesor profesor=(Profesor) session.get(Profesor.class, 101);
profesor.setNombre(“Pedro”));
session.update(profesor);
session.getTransaction().commit();
session.close()

74

Página 31

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Borrado
 Utilizaremos el método delete (Object objeto) con el objeto a borrar en la Base de Datos.
 Este método permite SOLO actualizar un UNICO Objeto

SI error parsing JNDI hibernate name
Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

:
Session session = sessionFactory.openSession();
session.beginTransaction();
Profesor profesor=(Profesor) session.get(Profesor.class, 101);
session.delete(profesor);
session.getTransaction().commit();
session.close()

75

Elementos Básicos de Hibernate
•

Elementos básicos:
5.- Clase Principal de Java. Operaciones CRUD
•

Inserción o Actualizar
 Hay veces que es útil realizar una Inserción o una Actualización en función de si el registro
existe o no.
 Disponemos del método saveOrUpdate (objeto) para realizar dichas acciones.
 Siempre deberemos validar la transacción antes de su finalización.

:
Profesor profesor=new Profesor(112, “Adriana", “Sanchez", “Meneses"); //Creamos el objeto
Session session = sessionFactory.openSession();
session.beginTransaction();

SI error parsing JNDI hibernate name

session.getTransaction().commit();
session.close()

Eliminar el elemento name del fichero hibernate.cfg.xml


© JAA JMA 2015

session.saveOrUpdate(profesor);

76

Página 32

Anotaciones JPA
•

Mediante los ficheros .hbm.xml podemos especificar cómo mapear la
clases Java en tablas de base de datos.

•

Pero….. cuando el desarrollo es grande, el número de ficheros
.hbm.xml puede ser desmesurado.

•

¿Cómo puedo hacer el mapeo sin utilizar ficheros XML?

•

Solución: Uso de Anotaciones Java
Estas anotaciones permiten especificar de una forma compacta y sencilla la
información de mapeo de las clases Java

© JAA JMA 2015

•

78

Anotaciones JPA
•

Hibernate dispone de sus propias anotaciones en el paquete
org.hibernate.annotations (a partir de la versión 4, la mayoría de dichas
anotaciones han sido marcadas como java.lang.Deprecated y ya no deben usarse)

•

Las anotaciones que deben usarse actualmente son las del estándar
de JPA que se encuentran en el paquete javax.persistence.

•

Sin embargo hay características específicas de Hibernate que no
posee JPA lo que hace que aun sea necesario usar alguna
anotación del paquete org.hibernate.annotations.

© JAA JMA 2015

(dichas anotaciones no han sido marcadas como Deprecated en Hibernate 4)

79

Página 33

Anotaciones JPA
Descripción
- Se aplica a la clase.
- Indica que esta clase Java es una entidad a persistir.

@Table(name="Tabla")

- Se aplica a la clase e indica el nombre de la tabla de la base de
datos donde se persistirá la clase.
- Es opcional si el nombre de la clase coincide con el de la tabla.

@Id

- Se aplica a una propiedad Java e indica que este atributo es la
clave primaria.

@Column(name="Id")

- Se aplica a una propiedad Java e indica el nombre de la
columna de la base de datos en la que se persistirá la
propiedad.
- Es opcional si el nombre de la propiedad Java coincide con el
de la columna de la base de datos.

@Column(…)

-

@Transient

- Se aplica a una propiedad Java e indica que este atributo no es
persistente

name: nombre
length: longitud
precision: número total de dígitos
scale: número de digitos decimales
unique: restriccion valor unico
nullable: restriccion valor obligatorio
insertable: es insertable
updatable: es modificable

© JAA JMA 2015

Anotación
@Entity

80

Anotaciones JPA
Import javax.persistence.*;
@Entity
@Table(name="Profesor")
public class Profesor implements Serializable {
@Id
@Column(name="Id")
private int id;
@Column(name="nombre")
private String nombre;

public int getId() { return id; }
public void setId(int id) { this.id = id; }

@Column(name="ape1")
private String ape1;
@Column(name="ape2")
private String ape2;

public String getNombre() { return nombre; }
public void setNombre(String nombre) { this.nombre = nombre; }
public String getApe1() { return ape1; }

public Profesor(){ }

public String getApe2() { return ape2; }
public void setApe2(String ape2) { this.ape2 = ape2; }
}

© JAA JMA 2015

public void setApe1(String ape1) { this.ape1 = ape1; }
public Profesor(int id, String nombre, String ape1, String ape2) {
this.id = id;
this.nombre = nombre;
this.ape1 = ape1;
this.ape2 = ape2;
}

81

Página 34

Anotaciones JPA
•

Para migrar de un proyecto Sin Anotaciones a uno con Anotaciones
JPA deberemos:
1. Modificar el fichero de configuración de Hibernate (hibernate.cfg.xml)
Todos los elementos de mapeos resource deben de ser eliminados



2. Modificar el la clase Principal de Java utilizado para crear el objeto sessionFactory.
Crear el objeto sessionFactory de la siguiente forma:

sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

© JAA JMA 2015

Configuration configuration = new Configuration(); configuration.configure();
ServiceRegistry serviceRegistry = new
ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);

82

Anotaciones JPA
NOTAS
•
•

El/los Fichero/s de mapeo Tabla.hbm.xml es obligatorio indicar todas las
propiedades que queremos que se persistan en la base de datos.
En las anotaciones no es necesario, persisten todas las propiedades que tengan
los métodos get/set.

Si colocamos las anotaciones sobre las propiedades, el acceso será a las
propiedades y no serán necesarios los métodos get/set.

•

Si colocamos las anotaciones sobre los métodos get() , el acceso será mediante
los métodos get/set.

© JAA JMA 2015

•

84

Página 35

Java Persistence API (JPA)
•

•
•

•

© JAA JMA 2015

•

JPA define un proceso de arranque diferente que usa su propio archivo
de configuración llamado persistence.xml distinto del archivo
hibernate.cfg.xml.
Este proceso de arranque está definido por la especificación JPA.
En entornos JavaSE, el proveedor de persistencia (Hibernate en este
caso) debe ubicar todos los archivos de configuración JPA en el
classpath con el nombre del recurso de META-INF/persistence.xml
(src/main/resources/META-INF)
Los archivos persistence.xml deben proporcionar un nombre único para
cada "unidad de persistencia".
Las aplicaciones utilizan este nombre para hacer referencia a la
configuración al obtener una referencia
javax.persistence.EntityManagerFactory.

85

persistence.xml
•

Crear directorio
• src/main/resources/META-INF

Crear fichero persistence.xml












© JAA JMA 2015

•

86

Página 36

EntityManagerFactory
•

La clase EntityManagerFactory nos permite crear un objeto
EntityManager para toda la comunicación, recibe el nombre de la "unidad
de persistencia".
• EntityManagerFactory emf =
Persistence.createEntityManagerFactory("dbPersistence");

•

La clase EntityManager contiene métodos para leer, guardar o borrar
entidades sobre la base de datos.
• EntityManager em = emf.createEntityManager();

•

En JEE con un contenedor EJB:

•

Para cerrar el gestor de entidades:

•

Para obtener el Session desde el EntityManager:

• em.close();
• Session session = em.unwrap( Session.class );

© JAA JMA 2015

• @PersistenceContext(unitName = "dbPersistence")
• private EntityManager em;

87

Transacciones con EntityManager
•

Creación de una transacción
• em.getTransaction().begin();

•

Validación de la transacción actual.
• em.getTransaction().commit();

•

Rollback de la transacción actual.
• em.getTransaction().rollback();

•

Consultar si la transacción esta activa.

© JAA JMA 2015

• if(em.getTransaction().isActive())

88

Página 37

Operaciones CRUD con EntityManager
•

Create:
• em.persist(…..);

•

Read:
• em.find(….);

•

Update (adjuntar):
• em.merge(…..); // Entidad detach

•

Delete:
• em.remove(….);

•

Persistencia sin transacciones (sincroniza con la base de datos):

•

Gestión a través de “entidades administradas”:
• Separar del contenedor: em.detach(…);
• Buscar en el contenedor: em.contains(…);
• Borrar contenedor: em.clear();

© JAA JMA 2015

• em.flush();

TIPOS DE DATOS Y CLAVES
PRIMARIAS

© JAA JMA 2015

89

91

Página 38

Tipos Básicos
•

Cuando trabajamos con un ORM, éste debe de ser capaz de trabajar
con los diferentes tipos de datos existentes:
 Tipos de datos en JAVA
 Tipos de datos en SQL

ORM debe de ser capaz de crear un puente entre ambos, totalmente
transparente para el desarrollador.

© JAA JMA 2015

•

93

Tipos Básicos
•

En toda aplicación que utiliza Hibernate, podemos diferenciar 3 tipos
de datos:
•
•
•

Tipos de Datos de Java → Ficheros .java
Tipos de Datos de SQL → Columnas de las tablas de la BBDD
Tipos de Datos de Hibernate → Ficheros de mapeo .hbm.xml

•

Estos tipos de datos Hibernate, son utilizados como conversores
para poder trasladar tipos de datos Java a SQL y viceversa.

•

Hibernate intentara determinar la conversión correcta y el tipo de
datos si el atributo type no se encuentra presente.

© JAA JMA 2015




94

Página 39

Tipos Básicos
•

Si no se especifica el tipo Hibernate, se produce una detección
automática, que es determinada mediante reflexión cuando se
procesan los ficheros de mapeo.

•

La detección automática, puede escoger un tipo que no es el que se
esperaba o necesitaba.
 Propiedad del tipo java.util.Date → ???? date
?
timestamp?
time
?

La detección automática, también conlleva un tiempo y recursos
extras.

© JAA JMA 2015

•

95

© JAA JMA 2015

Tipos Básicos

96

Página 40

© JAA JMA 2015

Tipos Básicos

97

Tipos Básicos
Fecha y Hora
• Cuando trabajamos con campos de Fecha y Hora deberemos tener
cuidado con la información que queremos tratar.
• Hay veces que sólo nos interesa:
 Fecha sin hora, minutos ni segundos
 Hora, sin día, mes, año
 Hora, sin milisegundos, microsegundos, etc…

• Deberemos seguir los siguientes criterios para el buen uso de estos
tipos de datos:

Hora, Minuto, Segundo
Timestamp
Hora, Minuto, Segundo
Día, Mes, Año

© JAA JMA 2015

Día, Mes, Año

98

Página 41

Tipos Básicos
Fecha y Hora
• Deberemos tener cuidado con:
 Si mapeamos una Variable Java (java.util.Date) con una columna Timestamp, Hibernate
devuelve un dato java.sql.Timestamp

timestamp

java.util.Date

java.sql.Timestamp

 Debemos de tener cuidado al utilizar el método equal() pues se producirá una
excepción objeto_Date.equal( Objeto_java.sql.Timestamp)

aDate.getTime() > bDate.getTime()

© JAA JMA 2015

• Si podremos realizar comparativas del modo:

99

Tipos Básicos
Boolean
• Hibernate permite 3 formas distintas de almacenar un booleano de Java
en la base de datos.
• Para ello existen 3 tipos de datos en Hibernate.
 boolean:
– Es la forma estándar de guardar un booleano en la base de datos.

 yes_no:
– El valor se guardará como un CHAR(1) con los valores de Y y N para true y false
respectivamente.

– El valor se guardará como un CHAR(1) con los valores de T y F para true y false
respectivamente.

© JAA JMA 2015

 true_false:

100

Página 42

@Temporal
•

Mediante anotaciones
@Temporal(TemporalType.DATE)
private Date fecha;
@Temporal(TemporalType.TIME)
private Date hora;
@Temporal(TemporalType.TIMESTAMP)
private Date momento;

•

Java 8 dispone de los nuevos tipos específicos soportados por Hibernate:
• FECHA
 java.time.LocalDate

• HORA
 java.time.LocalTime, java.time.OffsetTime
 java.time.Instant, java.time.LocalDateTime,
java.time.OffsetDateTimeYjava.time.ZonedDateTime

© JAA JMA 2015

• TIMESTAMP

101

Tipos Básicos
Texto
• Hibernate permite 2 formas distintas de almacenar un java.lang.String
de Java en la base de datos.
• Para ello existen 2 tipos de datos en Hibernate:
 string:
Se guardará el java.lang.String como un VARCHAR en la base de datos.

 text:

© JAA JMA 2015

Se guardará el java.lang.String como un CLOB o TEXT ,etc. en la base de datos.

102

Página 43

Tipos Básicos
Datos Binarios y Valores Grandes
• Si una propiedad en su clase Java persistente es de tipo byte [],
Hibernate puede asignarlo a una columna VARBINARY dentro de la
Base de Datos.
 El tipo VARBINARY depende del SGBDR
PostgreSQL
→
BYTEA
Oracle
→
RAW

• Si una propiedad en la clase Java es del tipo java.lang.String, y el tipo
de Hibernate es TEXT, puede asignarlo a una columna CLOB SQL en la
BBDD.

@Lob
@Column(name = "ITEM_DESCRIPTION")
private String description;

© JAA JMA 2015

• Si desea asignar un java.lang.String, char [], Character [], a una columna
CLOB, es necesario hacer una anotacion @Lob

103

Claves Primarias
•

En el diseño de bases de datos relacionales, se llama clave primaria
a un columna o combinación de columnas que identifica de forma
única a cada fila de una tabla.

•

Una clave primaria debe identificar unívocamente a todas las
posibles filas de una tabla actuales y futuras.

•

Propiedades que debe de cumplir:

•

Debe ser única
No puede ser NULL
A ser posible, nunca debería cambiar
Debe ser corta
Debe ser rápida de generar

En el modelo entidad-relación, la clave primaria permite las
relaciones entre tablas.

© JAA JMA 2015







104

Página 44

Claves Primarias
•

PK Naturales:
•

Una clave primaria natural es aquella columna/s de base de datos que actúa de
clave primaria en el modelo de negocio en el que estamos trabajando.
DNI, Número SS, Número de Cliente, etc

PK Artificiales:
•

Son aquellas claves que sin pertenecer al modelo de negocio hay que crear para
que todas las filas tengan un identificador, las "ideales" son las autonuméricas.

•

Si es posible, para Hibernate, es mejor utilizar Claves Primarias
Autonuméricas.

•

Estas PK pueden ser creadas de forma automática en Hibernate
mediante el TAG  en el fichero .hbm.xml.

•

Si Hibernate genera la clave primaria nos ahorramos
tener que incluirla en el constructor.

© JAA JMA 2015

•

105

Claves Primarias
•

Para definir las Claves primarias en Hibernate lo hacemos en el
fichero de mapeo de la clase Java donde esté la PK
 Introduciremos el TAG  junto con la forma de su generación
 

Profesor.hbm.xml












TAG 
Se utiliza para indicar que la clave primaria será
generada por el propio Hibernate en vez de asignarla
directamente el usuario.
class:
Indica el método que usará Hibernate para calcular la
clave primaria.
Si es “assigned” es una clave natural que no se
genera, se introduce manualmente.

© JAA JMA 2015




106

Página 45

© JAA JMA 2015

Claves Primarias

107

Claves Primarias Compuestas
•
•

Una tabla con clave compuesta se puede mapear con múltiples
propiedades de la clase como propiedades identificadoras.
El elemento  acepta los mapeos de propiedad  y los mapeos  como elementos hijos.

•

La clase persistente tiene que sobrescribir equals() y hashCode() para
implementar la igualdad del identificador compuesto. También tiene que
implementar Serializable.

© JAA JMA 2015






108

Página 46

Claves Primarias. Anotaciones
•

Para usar anotaciones deberemos modificar el código fuente de las
clases Java y no los ficheros .hbm.xml.
@Entity
@Table(name="Profesor")
public class Profesor implements Serializable {
@Id
@Column(name="Id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
:

Strategy=GenerationType.XXXXXXX
IIndica el método en el que Hibernate debe
generar la clave primaria
- AUTO
- IDENTITY
- SECUENCE

JPA no soporta todos los tipos de generaciones de Hibernate.
© JAA JMA 2015

•

@GeneratedValue:
Esta anotación indica que Hibernate deberá generar
el valor de la clave primaria.

109

Claves Primarias. Anotaciones
•

Si queremos hacer uso de todos los métodos de generación de
claves primarias de que dispone Hibernate mediante el uso de
anotaciones, deberemos usar la anotación propietaria de Hibernate.
•
•

@GeneratedValue( generator = "generador_propietario_hibernate_increment" )
@org.hibernate.annotations.GenericGenerator ( ….. )

@Id
@GeneratedValue( generator = "generador_propietario_hibernate_increment" )
@org.hibernate.annotations.GenericGenerator(
name = "generador_propietario_hibernate_increment",
strategy = "increment"
)
private int id;
:

© JAA JMA 2015

@Entity
@Table(name="Profesor")
public class Profesor implements Serializable {

110

Página 47

Claves Primarias Compuestas. Anotaciones
•

Es necesario crear una clase auxiliar que reúna los elementos de la
clave primaria y asociarla a la entidad.
@IdClass(ProfesorAsignaturaPK.class)
@Entity
@Table(name="ProfesorAsignatura")
public class ProfesorAsignatura implements Serializable {
@Id
@Column(name="IdProfesor")
private int idProfesor;
@Id
@Column(name="IdAsignatura")
private int idAsignatura;

@IdClass:
Especifica la clase de clave principal compuesta
que está asignado a múltiples campos o propiedades
de la entidad.

© JAA JMA 2015

Los nombres de los campos o propiedades de la clase
de clave principal y los campos de clave principal o
propiedades de la entidad deben corresponderse y
sus tipos deben ser los mismos.

111

Componentes
•

Lenguajes orientados a objetos como Java hacen más fácil definir
objetos complejos como composición de otros ya definidos.
•

Nombre Cliente, Dirección, Departamento → Objeto cliente
Objeto Dirección

Calle
Numero
Piso

Objeto Departamento
Objeto Empresa

NIF
Representante
País

Hibernate dispone de un elemento llamado Componente que
utilizamos para expresar este tipo de datos complejos.
© JAA JMA 2015

•

Código
Responsable
Ubicación

112

Página 48

Componentes
•

Los componentes son clases definidos por el usuario que son
persistentes dentro de la propia tabla.

•

Permiten que varias clases relacionadas se almacenen en una única
tabla de la BBDD.

Objeto Dirección

Calle
Numero
Piso

Objeto Departamento
Objeto Empresa

•

BBDD
Código
Responsable
Ubicación

Tabla
Única

NIF
Representante
País

•

© JAA JMA 2015

Estos componentes son tratados como un «value type», como un
Clase Dirección → String ( Calle+Numero+Piso)
tipo primitivo, String, etc
Los "value types" forman parte de una única clase

113

Componentes
•

Podríamos realizar el siguiente mapeado

Clase Profesor

Clase Nombre

•

Se han extraído las propiedades nombre, ape1 y ape2
en una nueva clase llamada Nombre, para poder tratarla
como un componente en Hbernate
Cuando hagamos Persistencia de Profesor y Nombre, se almacenarán dentro de
Tabla Profesor de forma única.

Componente

© JAA JMA 2015

•

114

Página 49

Componentes
•

Los componentes no requieren fichero de configuración .hbm.xml

•

El tag  se utiliza para especificar que la propiedad Java de la clase se
persistirá en la propia tabla de la clase principal.




Profesor.hbm.xml




© JAA JMA 2015









115

Componentes. Anotaciones
•

Para usar anotaciones deberemos modificar el código fuente de las
clases Java y no usar los ficheros .hbm.xml.

•

Deberemos indicar la anotación @Embedded en la propiedad que
sea el componente.
@Entity
@Table(name="Profesor")
public class Profesor implements Serializable {
@Id
@Column(name="Id")
private int id;

© JAA JMA 2015

@Embedded
private Nombre nombre;

@Embedded:
Esta anotación se usa para indicar que la propiedad
nombre se guardará en la misma tabla que Profesor.

116

Página 50

Componentes. Anotaciones
•

En la clase "Componente" deberemos introducir la anotación
@Embeddable al comienzo de la clase, en vez de @Entity

@Embeddable
public class Nombre implements Serializable {
@Column(name="nombre")
private String nombre;
@Column(name="ape1")
private String ape1;
@Column(name="ape2")
private String ape2;

@Embeddable:
Se usa para indicar que esta clase se usará como
un componente y que se guardará en la misma
tabla que la clase que la posee..

© JAA JMA 2015

:

117

Tipos Enumerados
•

Los tipos enumerados en Java, permiten que una variable tenga un
conjunto de valores restringidos.

•

Son utilizados con valores fijos ( meses del año, colores, etc)
public enum TipoFuncionario { Carrera, Practicas, Interino };
public enum Colores { Blanco, Negro, Amarillo, Rojo, Azul };

Hibernate no soporta directamente el persistir los enumerados.

•

Pero dispone de mecanismos sencillos para persistir un enumerado.

© JAA JMA 2015

•

118

Página 51

Tipos Enumerados
En el siguiente entorno:

© JAA JMA 2015

•

- Dentro de la Clase Profesor incluimos un dato Enumerado TipoFuncionario
- Dentro de la TABLA Profesor incluimos una columna INTEGER / VARCHAR

119

Tipos Enumerados
Sólo será necesario un fichero de persistencia profesor.hbm.xml











ejemplo06.TipoFuncionario
4





TAG 
Se utiliza para definir una forma personalizada
de persistir una propiedad Java.
Type name:
Indica la clase Java que sabe cómo persistir una
propiedad Java, en este caso los Enumerados.
Param name="enumClass">
Indica el Tipo Enumerado ha persistir
Param name ="type">
Debe de ser el tipo de persistencia a realizar:
1 → CHAR
2 → NUMERIC
4 → INTEGER
5 → SMALLINT
12 → VARCHAR

© JAA JMA 2015

•

120

Página 52

Tipos Enumerados

12

© JAA JMA 2015

4

121

Especiales
•

Especificar que se debe recuperar perezosamente esta propiedad cuando se
acceda por primera vez la variable de instancia.
@Basic(fetch = FetchType.LAZY)
@Lob
private Blob image;

•

Se puede especificar una expresión SQL que define el valor para una propiedad
calculada, no tienen una columna mapeada propia y se recupera ya calculada.
@Formula(value = "credit * rate")
private Double interest;

Es necesario especificar las columnas calculadas, solo lectura, cuyas
propiedades debe ignorar la persistir:
•
•

INSERT: el valor de propiedad se genera en la inserción pero no se regenera en
actualizaciones posteriores.
ALWAYS: el valor de la propiedad se genera tanto en la inserción como en la
actualización.
@Generated( value = GenerationTime.ALWAYS )
private Date timestamp;

© JAA JMA 2015

•

122

Página 53

•
•
•
•

•
•

•

El patrón Proxy es un patrón estructural que tiene como propósito proporcionar un
subrogado o intermediario de un objeto para controlar su acceso.
Un proxy es una clase que envuelve (hereda) a otra para poder retrasar el coste de crear e
inicializar un objeto hasta que es realmente necesario.
Hibernate utiliza proxys para implementar las cargas perezosas de forma transparente.
Hibernate usa bibliotecas de manipulación de Bytecode como Javassist o Byte Buddy, que
hacen uso de la reflexión para modificar la implementación de una clase en tiempo de
ejecución .
La colección org.hibernate.collection.internal.PersistentBag envuelve las colecciones con
carga perezosa.
Para evitar problemas (y seguir los buenos principios de diseño) es importante que las
colecciones se definan utilizando la interfaz adecuada de Java Collections Framework en
lugar de una implementación específica, Hibernate (como otros proveedores de
persistencia) utilizará sus propias implementaciones de colección que se ajustan a las
interfaces de Java Collections Framework.
Las colecciones persistentes inyectadas por Hibernate se comportan como ArrayList,
HashSet, TreeSet, HashMapo TreeMap, en función del tipo de interfaz.

© JAA JMA 2015

Proxy

123

Tipos de Proxy
•

Dependiendo de las responsabilidades y del comportamiento del proxy,
tendremos varios tipos que realizarán unos tipos de tarea u otras. Los
proxies más comunes son los siguientes:

•

El patrón proxy modifica el comportamiento pero no amplia la
funcionalidad, para ello se utilizaría patrones como Adapter o Decorator.

© JAA JMA 2015

• Proxy remoto: un proxy remoto se comporta como un representante local de
un objeto remoto. Se encarga principalmente de abstraer la comunicación
entre nuestro cliente y el objeto remoto. Es el embajador de los proxies.
• Proxy virtual: se encarga de instanciar objetos cuyo coste computacional es
elevado. Es capaz de sustituir al objeto real durante el tiempo que el
verdadero objeto está siendo construido y proporcionar funcionalidades como
el lazy loading (realizar operaciones computacionalmente costosas
únicamente cuando el acceso a el elemento es requerido).
• Proxy de protección: establece controles de acceso a un objeto dependiendo
de permisos o reglas de autorización.

124

Página 54

•

•

•

El Elemento es una clase abstracta (o interfaz) que define las
operaciones que deberá cumplimentar tanto el objeto real
(ElementoReal) como el proxy que actuará de intermediario
(ElementoProxy). Ambos elementos, al heredar de Elemento, deberán
ser, por tanto, intercambiables. De este modo, sustituir un objeto de la
clase ElementoReal por un ElementoProxy debería de ser -idealmentetransparente.
La clase ElementoReal es aquella que contiene la verdadera
funcionalidad, es decir, la clase original que se quiere “proteger” a través
del proxy.
La clase ElementoProxy también hereda de Elemento, y como tal, posee
todos sus métodos. La diferencia fundamental es que incorpora una
referencia a otro ElementoReal y sus métodos actúan como pasarela a
los métodos del ElementoReal.

© JAA JMA 2015

Estructura del patrón Proxy

125

© JAA JMA 2015

Estructura del patrón Proxy

126

Página 55

public abstract class Elemento {
public abstract void metodo();
}
public class ElementoReal extends Elemento {
@Override
public void metodo() { }
}
public class ElementoProxy extends Elemento {
private ElementoReal objeto;
private ElementoReal getObjeto() {
if(objeto == null) objeto = new ElementoReal();
return objeto;
}
@Override
public void metodo() {
getObjeto().metodo();
}
}

© JAA JMA 2015

Implementación del patrón Proxy

127

Problemas con los Proxy Hibernate
•

Cuando se difiere la carga, Hibernate sustituye la instancia real por un proxy heredero de la
real:
Entidad e = session.getReference(Entidad.class, 1001L); // Tipo: Entidad$HibernateProxy$3UWSrq7i

•
•

Lo cual presenta problemas con las clases entidad selladas, en cuyo caso no genera un
proxy, materializa la consulta.
Para evitar la materialización es necesario generar, implementar y asociar manualmente el
interfaz que actuará de proxy:

@Entity
@Proxy(proxyClass = EntidadProxy.class)
public final class Entidad implements Serializable, EntidadProxy { … }
Entidad e = session.getReference(Entidad.class, 1001L); // ERROR
EntidadProxy e = session.getReference(Entidad.class, 1001L); // OK

© JAA JMA 2015

public interface EntidadProxy {
long getId();
void setId(long id);
}

128

Página 56

Proxys LOBs
•

Los localizadores JDBC LOB existen para permitir un acceso eficiente a los datos LOB
(Blob, Clob, NClod). Permiten que el controlador JDBC transmita partes de los datos LOB
según sea necesario, lo que potencialmente libera espacio en la memoria. Sin embargo,
pueden ser poco naturales de tratar y tienen ciertas limitaciones, para facilitar su manejo
Hibernate suministra el correspondiente juego de proxys:
@Entity(name = "Product")
public static class Product {
@Lob
private Blob image;
}

final Product product = new Product();
product.setImage( BlobProxy.generateProxy( image ) );
// …
try (InputStream inputStream = product.getImage().getBinaryStream()) {
// …
}

© JAA JMA 2015

byte[] image = new byte[] {1, 2, 3};

129

Conversores
@Converter
public class PeriodStringConverter implements AttributeConverter {
@Override
public String convertToDatabaseColumn(Period attribute) {
return attribute.toString();
}
@Override
public Period convertToEntityAttribute(String dbData) {
return Period.parse( dbData );
}

@Convert(converter = PeriodStringConverter.class)
@Column(columnDefinition = "")
private Period span;

© JAA JMA 2015

}

130

Página 57

Filtro de entidades
•

A veces, se desea filtrar entidades o colecciones utilizando criterios SQL
personalizados:
@Entity(name = "Account")
@Where( clause = "deleted = false" )
public static class Account {

La anotación @Filter es otra forma de filtrar entidades o colecciones
utilizando criterios SQL personalizados pero permite parametrizar la
cláusula de filtro en tiempo de ejecución.
@Entity(name = "Account")
@FilterDef(name="activeAccount", parameters = @ParamDef(
name="active", type="boolean"))
@Filter(name="activeAccount", condition="active_status = :active")
public static class Account {

•

Los @Filter se activan al realizar las consultas.

© JAA JMA 2015

•

131

Inmutabilidad

•

Si una entidad específica es inmutable, no van a cambiar sus datos, es una
buena práctica marcarla con la anotación @Immutable.
Cuando una entidad es de solo lectura:
•
•
•
•

Hibernate no comprueba las propiedades simples de la entidad o las asociaciones de
un solo extremo;
Hibernate no actualizará propiedades simples o asociaciones actualizables de un solo
extremo;
Hibernate no actualizará la versión de la entidad de solo lectura si solo se modifican
propiedades simples o asociaciones actualizables de un solo extremo;
Hibernate reducirá el uso de memoria, ya que no es necesario retener el estado para el
mecanismo de gestión de cambios.

•

También las colecciones pueden marcarse como @Immutable, el efecto será
local a la colección.

•

Las propiedades simples no se pueden marcar como @Immutable pero se
pueden definir como:
@Column(insertable=false, updatable=false)

© JAA JMA 2015

•

132

Página 58

Método Equals
•

Cuando en Java queremos comprobar si 2 objetos son idénticos,
utilizamos el método equals().

•

En Hibernate esto difiere.
•

2 objetos son iguales si hacen referencia a la misma fila de la base de datos
aunque los objetos sean distintos.

Este carácter especial hace que existan algunos "inconvenientes" a
la hora de implementar esta comprobación en Hibernate.

•

La igualdad de clave de principal significa que el método equals()
solamente debe comparar las propiedades que forman la clave de
principal.
© JAA JMA 2015

•

133

Método Equals
public class Entidad {
...
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof Entidad) ) return false;
return this.getId().Equals(((Entidad)other).getId());

}

© JAA JMA 2015

}
public int hashCode() {
return this.getId();
}

134

Página 59

© JAA JMA 2015

ASOCIACIONES CON
HIBERNATE

136

Asociaciones en Hibernate
•

Existen 2 temas importantes cuando empezamos a desarrollar en
Hibernate:
•
•

Mapeo de asociaciones entre las clases de entidad.
Mapeo de colecciones

Hasta ahora hemos visto el mapeo simple entre una clase y una
entidad, pero la base de datos no contienen solo tablas aisladas, la
tablas tienen relaciones dentro de las BBDD.

•

Todos los mapeos que vamos a realizar pueden hacer con sus
correspondiente fichero .hbm.xml o con anotaciones JPA.

© JAA JMA 2015

•

138

Página 60

Asociaciones en Hibernate
•

Cuando utilizamos la palabra asociación, nos referimos a la relación
existente entre tablas de la Base de Datos (entidades).

•

Básicamente se podrían definir las siguientes asociaciones:
Uno a uno (unidireccional)
Uno a uno (bidireccional)
Uno a muchos (desordenada)
Uno a muchos (ordenada)
Muchos a muchos

© JAA JMA 2015

•
•
•
•
•

139

Asociaciones en Hibernate
Uno a uno
La relación uno a uno en Hibernate consiste en que un objeto tenga una
referencia a otro objeto de forma que al persistirse el primer objeto también se
persista el segundo.

•

Si en el Modelo Relacional encontramos PK-FK entre entidades, entonces
deberemos crear una Asociación de 1 a muchos

•

Este tipo de relación se puede crear cuando "necesitemos" establecer una
relación entre entidades que no tengan columnas comunes ni relacionadas.

© JAA JMA 2015

•

140

Página 61

Asociaciones en Hibernate
Uno a uno
• En Hibernate se puede diferenciar 2 tipos de relaciones uno-a-uno:
• Unidireccional
 Cuando se hace la persistencia del primer Objeto, también se hace del objeto
referenciado, pero no a la inversa.

• Bidireccional

© JAA JMA 2015

 Cuando se hace la persistencia del primer Objeto, también se hace del objeto
referenciado, y a la inversa.
 Cuando se hace la persistencia del objeto referenciado se puede hacer o no la del
primer Objeto.

141

Asociaciones en Hibernate
Uno a uno (Unidireccional)
 Cuando 1 objeto tiene una referencia a otro objeto, cuando hacemos persistir
el primero, también se hace la persistencia del segundo.
 Este tipo de relaciones pueden darse cuando en una entidad (Profesor)
queremos asignarle una Dirección y no queremos/tenemos una columna(FK)
con la clave de Dirección
 ¿Cómo se establece la relación entre las dos filas?

public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private Direccion direccion;
public Profesor() { }
public Profesor (int id, String nombre, String ape1, String ape2) {
:

© JAA JMA 2015

– Simplemente porque ambas Entidades ( Profesor como Dirección) deben
tener la misma ID y de esa forma se establece la relación.

142

Página 62

Asociaciones en Hibernate
Uno a uno (Unidireccional)
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

 Similares a este: (profesor.hbm.xml)











TAG 
Se utiliza para definir una relación uno a uno entre las
dos clases Java.
name:
Nombre de la propiedad Java con la referencia al otro
objeto con el que forma la relación uno a uno.
cascade:
Indica a Hibernate cómo debe actuar cuando
realicemos las operaciones de persistencia CRUD.
ALL hacer lo mismo en el objeto referenciado




© JAA JMA 2015

Profesor.hbm.xml

Profesor.hbm.xml
Direccion.hbm.xml

143

Asociaciones en Hibernate
Uno a uno (Unidireccional)
 Sin embargo en el fichero de persistencia de Direccion.hbm.xml, no se hará
ninguna referencia al tag 

Direccion.hbm.xml











 La relación uno a uno tiene una direccionalidad desde Profesor → Dirección
por lo tanto Dirección no sabe nada sobre Profesor y por ello en su fichero de
persistencia no hay nada relativo a dicha relación.

© JAA JMA 2015




144

Página 63

Asociaciones en Hibernate
Uno a uno (Unidireccional) con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Sólo deberemos introducir las anotaciones relacionadas con one-to-one en la
clase Profesor y en el elemento de unión de ambas.

@OneToOne(cascade=CascadeType.ALL):
Esta anotación indica la relación uno a uno de las 2 tablas.
También indicamos el valor de cascade al igual que en el fichero de Hibernate.
:

@PrimaryKeyJoinColumn:

@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private Direccion direccion;

Hibernate entiende por Clave primaria, el identificador ID de cada
una de las tablas, no una PK de SGBDR

}
:

© JAA JMA 2015

@Column(name="ape2")
private String ape2;

Indicamos que la relación entre las dos tablas se realiza mediante
la clave primaria.

146

Asociaciones en Hibernate
Uno a uno (Bidireccional)
 Este tipo de relaciones aparecen cuando 1 objeto tiene una referencia a otro
objeto, cuando hacemos persistir el primero, también se hace la persistencia
del segundo y viceversa.
 Para hacer esta implementación deberemos tener en ambas clases de Java
una referencia a una instancia del otro componente:
– Profesor → Dirección
– Dirección → Profesor

Profesor.hbm.xml

public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private Direccion direccion;
public class Direccion implements Serializable {
private int id;
private String calle;
public Profesor (int id, String nombre, String ape1, String ape2) {
private int numero;
:
private String poblacion;
private String provincia;
private Profesor profesor;

Dirección.hbm.xml

© JAA JMA 2015

public Profesor() { }

147

Página 64

Asociaciones en Hibernate
Uno a uno (Bidireccional)
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

 Deberemos poner el TAG de  en ambos ficheros .hbm.xml













TAG 
Se utiliza para definir una relación uno a uno entre las
dos clases Java.
name:
Nombre de la propiedad Java con la referencia al otro
objeto con el que forma la relación uno a uno.
cascade:
Indica a Hibernate cómo debe actuar cuando
realicemos las operaciones de persistencia CRUD.
ALL hacer lo mismo en el objeto referenciado

:





Dirección.hbm.xml

© JAA JMA 2015

Profesor.hbm.xml

Profesor.hbm.xml
Direccion.hbm.xml

148

Asociaciones en Hibernate
Uno a uno (bidireccional) con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Sólo deberemos introducir las anotaciones relacionadas con one-to-one en
las clase Profesor y Direccion en el elemento de unión de ambas.

@OneToOne(cascade=CascadeType.ALL):
Esta anotación indica la relación uno a uno de las 2 tablas.
También indicamos el valor de cascade al igual que en el fichero de
Hibernate.

:
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private Direccion direccion;
}

Indicamos que la relación entre las dos tablas se realiza mediante
la clave primaria.

:
:
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
private Profesor profesor;

Hibernate entiende por Clave primaria, el identificador ID de cada
una de las tablas, no una PK de SGBDR

}
:

© JAA JMA 2015

@PrimaryKeyJoinColumn:

150

Página 65

Asociaciones en Hibernate
Uno a Muchos
•

La relación uno a muchos consiste en que un objeto (padre) tenga una lista sin
ordenar de otros objetos (hijo) de forma que al persistirse el objeto principal
también se persista la lista de objetos hijo.

•

Esta relación también suele llamarse maestro-detalle o padre-hijo.
–
–
–
–

•

Clientes → Facturas
Facturas → Líneas de Detalle
Provincias → Localidades
Departamentos → Empleados

Podemos distinguir 2 tipos de Asociaciones:
 Uno a Muchos Desordenados
 Uno a Muchos Ordenados

Habitualmente la lista de objetos usadas son colecciones ( Set, List, etc) y
dependiendo de la colección utilizada se designan Ordenados o Desordenados.
© JAA JMA 2015

•

151

Asociaciones en Hibernate
Uno a Muchos Desordenados
•

Para poder realizar este tipo de asociaciones necesitamos una Bidireccionalidad
entre ambas (padre-hijo).

•

En Java almacenamos la serie de objetos hijos mediante el interface SET o
cualquier otra colección que no implique orden de los objetos (List , Array, Tree no).

En este tipo de relaciones existe
una PK y una FK en las tablas
relacionales

•
•

Id(profesor) →PK
idProfesor(correo) → FK
© JAA JMA 2015

•

152

Página 66

Asociaciones en Hibernate
Uno a Muchos Desordenados
•

Para hacer esta implementación deberemos tener en ambas clases de Java una
referencia a una instancia del otro componente:

•
•

Profesor → set  correosElectronicos
CorreoElectronico → Profesor

public class CorreoElectronico implements Serializable {
private int idCorreo;
private String direccionCorreo;
private Profesor profesor;
:

© JAA JMA 2015

public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private Set correosElectronicos;
:

153

Asociaciones en Hibernate
Uno a Muchos Desordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml

Profesor.hbm.xml
CorreoElectronico.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase PADRE
TAG 










Se utiliza para definir una relación uno a muchos
desordenada entre 2 clases
name:
Nombre de la propiedad SET en la que se almacenan los
objetos.

cascade:
Indica a Hibernate cómo debe actuar cuando realicemos
las operaciones de persistencia CRUD.
ALL hacer lo mismo en el objeto referenciado

inverse:
Usado para minimizar las operaciones SQL que hace
Hibernate contra la BBDD

© JAA JMA 2015

:







154

Página 67

Asociaciones en Hibernate
Uno a Muchos Desordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml

Profesor.hbm.xml
CorreoElectronico.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase PADRE

:







TAG 










:

Se utiliza para definir una relación uno a muchos
desordenada entre 2 clases
key:
Nombre de la columna de la BBDD que actúa como clave
Foranea FK en la relación

© JAA JMA 2015

Contiene la clase de Java que actúa como HIJA en la
relación.

155

Asociaciones en Hibernate
Uno a Muchos Desordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml
CorreoElectronico.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase HIJA
CorreoElectronico.hbm.xml







TAG 
Se utiliza para definir una relación de mucho a uno
entre 2 clases
name:
Nombre de la PROPIEDAD JAVA que enlaza con el
objeto PADRE, es decir, la variable declarada para
referenciar al padre.

Column name:
Indica la columna de la Tabla Hija que actúa como FK

© JAA JMA 2015








156

Página 68

Asociaciones en Hibernate
Uno a Muchos Desordenados con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Sólo deberemos introducir las anotaciones:
PADRE
HIJO

Profesor.java

(Profesor)
(correoElectronico)

@oneToMany
@ ManyToOne @JoinColumn

:
@OneToMany(mappedBy="profesor",cascade= CascadeType.ALL)
private Set correosElectronicos; }
:

@OneToMany(mappedBy="profesor",cascade= CascadeType.ALL)
mappedBy:


Este atributo contendrá el Nombre de la PROPIEDAD JAVA de la clase HIJA que enlaza con el objeto PADRE,
es decir, la variable declarada para referenciar al padre.

cascade


Este atributo tiene el mismo significado que el del fichero de mapeo de Hibernate.

© JAA JMA 2015

Esta anotación indica la relación uno a Muchos

158

Asociaciones en Hibernate
Uno a Muchos Desordenados con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Sólo deberemos introducir las anotaciones:
correoElectronico.java

PADRE
HIJO

(Profesor)
(correoElectronico)

@oneToMany
@ManyToOne @JoinColumn

:
@ManyToOne
@JoinColumn(name="IdProfesor")
private Profesor profesor;
:

@ManyToOne
@JoinColumn ( name="idProfesor")
Indicaremos el nombre de la columna que en la tabla hija contiene la clave ajena a la tabla padre.

© JAA JMA 2015

Esta anotación indica la relación de Muchos a uno

159

Página 69

Asociaciones en Hibernate
•

Para poder realizar este tipo de asociaciones necesitamos una Bidireccionalidad
entre ambas (padre-hijo).

•

En Java almacenamos la serie de objetos hijos mediante el interface LIST o
cualquier otra colección que implique orden de los objetos (List , Array, Tree).

•
•

Id(profesor) →PK
idProfesor(correo) → FK

•

Idx → Columna adicional para
indicar orden de los hijos

•

Las clases ejemplo utilizadas
serán idénticas a las anteriores
pero utilizando una colección
ordenada

© JAA JMA 2015

Uno a Muchos Ordenados

160

Asociaciones en Hibernate
Uno a Muchos Ordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml
CorreoElectronico.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase PADRE
Profesor.hbm.xml



  

TAG 
Se utiliza para definir una relación uno a muchos
entre 2 clases en las cuales hay un orden
name:
Nombre de la propiedad SET en la que se almacenan los
objetos.

cascade:
Indica a Hibernate cómo debe actuar cuando realicemos
las operaciones de persistencia CRUD.
ALL hacer lo mismo en el objeto referenciado

inverse:
Usado para minimizar las operaciones SQL que hace
Hibernate contra la BBDD

© JAA JMA 2015













161

Página 70

Asociaciones en Hibernate
Uno a Muchos Ordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

 Deberemos poner el TAG de  en el fichero de la clase PADRE




  












TAG 
Se utiliza para definir una relación uno a muchos
desordenada entre 2 clases
key:
Nombre de la columna de la BBDD que actúa como clave
Foranea FK en la relación

List-index: Column name
Nombre de la columna de la tabla HIJA donde se guarda
el orden que ocupan dentro de la Lista.

:
Contiene la clase de Java que actúa como HIJA en la
relación.

© JAA JMA 2015

Profesor.hbm.xml

Profesor.hbm.xml
CorreoElectronico.hbm.xml

162

Asociaciones en Hibernate
Uno a Muchos Ordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml
CorreoElectronico.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase HIJA
CorreoElectronico.hbm.xml







TAG 
Se utiliza para definir una relación de mucho a uno
entre 2 clases
name:
Nombre de la PROPIEDAD JAVA que enlaza con el
objeto PADRE, es decir, la variable declarada para
referenciar al padre.

Column name:
Indica la columna de la Tabla Hija que actúa como FK

© JAA JMA 2015








163

Página 71

Asociaciones en Hibernate
Uno a Muchos Ordenados con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Deberemos introducir las siguientes anotaciones:
Profesor.java

PADRE
HIJO

(Profesor)
(correoElectronico)

@oneToMany @JoinColum @IndexColumn
@ManyToOne @JoinColum

@OneToMany(cascade= CascadeType.ALL)
@JoinColumn(name="IdProfesor")
@IndexColumn(name="idx")
private List correosElectronicos;

@OneToMany(mappedBy="profesor",cascade= CascadeType.ALL)
@JoinColumn ( name="idProfesor")
Indicaremos el nombre de la columna que en la tabla hija contiene la clave ajena a la tabla padre.

@IndexColumn ( name="idx")
Indicaremos el nombre de la columna que en la tabla hija contiene el orden dentro de la Lista

© JAA JMA 2015

Esta anotación indica la relación uno a Muchos y es idéntica a la anterior usada

165

Asociaciones en Hibernate
Uno a Muchos Ordenados con JPA
 Al igual que en los casos anteriores, cuando utilizamos anotaciones JPA
deberemos modificar el código fuente de las clases Java y no usar los
ficheros .hbm.xml.
 Deberemos introducir las siguientes anotaciones:
correoElectronico.java

PADRE
HIJO

(Profesor)
(correoElectronico)

@oneToMany @JoinColum @IndexColumn
@ManyToOne @JoinColum

:
@ManyToOne
@JoinColumn(name="IdProfesor")
private Profesor profesor;:

@ManyToOne
@JoinColumn ( name="idProfesor")
Indicaremos el nombre de la columna que en la tabla hija contiene la clave ajena a la tabla padre.

© JAA JMA 2015

Esta anotación indica la relación de Muchos a uno

166

Página 72

Asociaciones en Hibernate
•

La relación muchos a muchos consiste en que un objeto A tenga una lista de
otros objetos B y también que el objeto B a su vez tenga la lista de objetos A.

•

De forma que al persistirse cualquier objeto también se persista la lista de objetos
que posee.

•

En este tipo de relaciones, aparece una nueva Entidad (Renacida) que sirve de
conexión entre ambas dos.

•

Habitualmente las listas de objetos utilizadas son colecciones ( Set, HashSet,
TreeSet, etc) y dependiendo de la colección utilizada se designan Ordenados o
Desordenados.

•

Ejemplo:
 Profesores → Asignaturas
 Asignaturas → Profesores

Profesor

Profesor
Asignatura

Asignatura

© JAA JMA 2015

Muchos a Muchos

167

Asociaciones en Hibernate
Muchos a Muchos
En Relacional, en toda asociación muchos a muchos se descompone en una
Entidad Renacida (ProfesorAsignatura) que contiene las PK de cada una de las
Entidades.

Create Table ProfesorAsignatura(
id int(11) references Profesor(id),
IdAsignatura int(11) references Asignatura(idAsignatura));

Create Table Asignatura(
idAsignatura int(11),
Nombre varchar(255) )

© JAA JMA 2015

•

168

Página 73

Asociaciones en Hibernate
Muchos a Muchos
•

Dentro de cada una de las clases, deberemos tener una referencia a un conjunto
de objetos de la otra clase.

•

Esta referencia e implementa mediante colecciones (Set)
Profesor

Profesor
Asignatura

public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private Set asignatura=new HashSet();

Asignatura
public class Asignatura implements Serializable {
private int idAsignatura;
private String nombre;
private Set profesores=new HashSet();
public Asignatura() { }

public Profesor(int id, String nombre, String ape1, String ape2)
{ this.id = id;
this.nombre = nombre;
this.ape1 = ape1;
this.ape2 = ape2;
}
}

public Asignatura (int id Asignatura, String nombre) {
this.id Asignatura = idAsignatura;
this.nombre = nombre;
}
}

© JAA JMA 2015

public Profesor(){ }

169

Asociaciones en Hibernate
Muchos a Muchos
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

Profesor.hbm.xml
Asignatura.hbm.xml

 Deberemos poner el TAG de  en el fichero de la clase PADRE
Profesor.hbm.xml



  

TAG 
Se utiliza para definir una relación muchos a muchos
entre 2 clases en las cuales hay un orden
name:
Nombre de la propiedad SET en la que se almacenan los
objetos.

table:
Nombre de la tabla RENACIDA.

cascade:
Indica a Hibernate cómo debe actuar cuando realicemos
las operaciones de persistencia CRUD.
ALL hacer lo mismo en el objeto referenciado

inverse:
Usado para minimizar las operaciones SQL que hace
Hibernate contra la BBDD

© JAA JMA 2015










170

Página 74

Asociaciones en Hibernate
Muchos a Muchos Ordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

 Deberemos poner el TAG de  en el fichero de la clase PADRE




  









TAG 
Se utiliza para definir una relación uno a muchos
desordenada entre 2 clases
key:
Nombre de la columna de la RENACIDA que actúa como
clave Foranea FK en la relación con esta tabla.

:
Contiene la clase de Java que actúa como HIJA en la
relación.

© JAA JMA 2015

Profesor.hbm.xml

Profesor.hbm.xml
Asignatura.hbm.xml

171

Asociaciones en Hibernate
Muchos a Muchos Ordenados
 Al estar utilizando 2 entidades necesitamos 2 archivos de persistencia
.hbm.xml
–
–

 Deberemos poner el TAG de  en el fichero de la clase PADRE














TAG 
Se utiliza para definir una relación uno a muchos
desordenada entre 2 clases
key:
Nombre de la columna de la RENACIDA que actúa como
clave Foranea FK en la relación con esta tabla.

:
Contiene la clase de Java que actúa como HIJA en la
relación.

© JAA JMA 2015

Asignatura.hbm.xml

Profesor.hbm.xml
Asignatura.hbm.xml

172

Página 75

Atributo: Cascade
•

Como hemos visto anteriormente, el atributo cascade se utiliza en
los mapeos de las Asociaciones..

•

Este atributo indica qué debe hacer Hibernate con las clases
relacionadas cuando realizamos alguna acción con la clase principal.
 Si borramos en la Principal → ¿Tenemos que borrar en la clase Hija?
 Si insertamos en la Principal → …….

Este atributo tiene 11 valores dependiendo de nuestros modelos de
clases.

•

Es útil cuando queremos que las asociaciones se comporten de
forma especial.
© JAA JMA 2015

•

173

Atributo: Cascade
Valor

Descripción

none

- No se hace nada en la clase Hija

Save-update

- Si se inserta o actualiza el objeto principal también se realizará la inserción o
actualización en los objetos relacionados.

delete

- Si se borra el objeto principal también se realizará el borrado en los objetos
relacionados.

evict
lock
merge
refresh
replicate

- Si se llama al método

all

- Si se realiza cualquiera de las anteriores acciones sobre el objeto principal
también se realizará sobre los objetos relacionados

delete-orphan

- Solo se usa con colecciones
- Si en una colección del objeto principal eliminamos un elemento, al persistir el
objeto principal deberemos borrar de la base de datos el elemento de la
colección que habíamos eliminado.

all-delete-orphan

- Es la unión de los atributos all y delete-orphan

Session.XXXXXXXX(Object objeto)

© JAA JMA 2015

para separar, bloquear, mezclar, refrescar o replicar el objeto principal también
se llamará para los objetos relacionados

174

Página 76

Cascada con anotaciones
•

Parámetro cascade de la anotación:
@OneToMany(mappedBy="profesor", cascade=CascadeType.ALL)

Enumeración de tipo CascadeType:
•
•
•
•
•
•

•

ALL = {PERSIST, MERGE, REMOVE, REFRESH, DETACH}
DETACH
MERGE
PERSIST
REFRESH
REMOVE

Acepta múltiples valores:
@OneToMany(mappedBy="profesor", cascade={CascadeType.PERSIST,
CascadeType.MERGE})

© JAA JMA 2015

•

175

Lazy Loading (Carga Perezosa)
•

Lazy Loading es la estrategia de recuperación del Hibernate
asociada a Colecciones.

•

Cuando intentemos recuperar los objetos de A se hará un consulta a
la base de datos para recuperar los datos de la tabla TA, pero no se
traerá los datos correspondientes de la tabla TB.

•

Los datos de la TB se recuperarán cuando la aplicación invoca una
operación sobre esa colección.
Si disponemos de un objeto que puede tener varios hijos, no recuperamos esos
hijos hasta que los vayamos a utilizar
 Profesores → Direcciones
 Profesores → CorreosElectronicos

@OneToMany(fetch=FetchType.LAZY)
@OneToMany(fetch=FetchType.EAGER)

1→N
1→N



© JAA JMA 2015

•

176

Página 77

Lazy Loading (Carga Perezosa)
En la primera petición, se proporcionará un proxy (gestor) que se
encargará de hacer las consultas a la base de datos cuando
realmente se consulta la colección de objetos de la clase B
•

•

Visto desde Hibernate:
•

•

PROXY: Es un mecanismo que permite a Hibernate romper la interconexión de los objetos en
la base de datos en fragmentos más pequeños, que pueden caber fácilmente en la memoria.

Esta aproximación es adecuada, ya que no se recuperan los datos de TB si no son realmente
necesarios.

Visto desde BBDD
•

Esta aproximación es ineficiente, ya que se hacen demasiadas consultas para recuperar una
información que podríamos obtener con una sola consulta

© JAA JMA 2015

•

177

Lazy Loading (Carga Perezosa)
•

Configuración:
•

Lazy
 Define el “cuando” se cargan datos.
 Por defecto lazy es igual a true. Esto significa que la colección no se recupera de la base de datos
hasta que se hace alguna operación sobre ella.
 Si fijamos lazy a false, cuando se recupere la información de A también se traerá toda la información
de los objetos relacionados de B.

@OneToMany(mappedBy="profesor", fetch=FetchType.LAZY) // Por defecto

•

Fetch


@OneToMany(mappedBy="profesor", fetch=FetchType.EAGER)

© JAA JMA 2015

 Define con que SQLs se van a lanzar para recuperar la información.
 Por defecto fetch es igual a select. Esto implica que para recuperar cada objeto de B se lanzará una
nueva consulta a la base de datos.
 Si fijamos el valor de fetch a join, en la misma consulta que se recupera la información de A también se
recuperará la información de todos los objetos relacionados de B. Esto se consigue con un left outer
join en la sentencia SQL.

178

Página 78

Mapeo de Herencia
•

Hibernate soporta las tres estrategias básicas de mapeo de herencia:
• tabla por jerarquía de clases
• tabla por subclases
• tabla por clase concreta

•
•
•

© JAA JMA 2015

•

Se modelizan a través de relaciones OR del modelo relacional.
Es posible utilizar estrategias de mapeo diferentes para diferentes
ramificaciones de la misma jerarquía de herencia.
Es posible definir los mapeos subclass, union-subclass, y joined-subclass
en documentos de mapeo separados, directamente debajo de hibernatemapping.
Esto permite extender una jerarquía de clases solamente añadiendo un
nuevo archivo de mapeo.

179

Tabla por jerarquía de clases
•

Requiere una sola tabla con:
•
•
•
•

•

Identificador común
Discriminador que establece a que subclase pertenece
Propiedades de la clase base, comunes a todas sus subclases
Propiedades particulares de cada subclase

Hay una limitación en esta estrategia de mapeo:

© JAA JMA 2015

• La columna discriminador es obligatoria.
• Las columnas declaradas por las subclases, no pueden tener restricciones
NOT NULL.

180

Página 79







...


...


...


...



© JAA JMA 2015

Tabla por jerarquía de clases

181

Anotaciones para Tabla por jerarquía de clases
@Entity(name = "Account")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="PAYMENT_TYPE")
public abstract class Account { … }

@Entity(name = "CreditAccount")
@DiscriminatorValue( "Credit" )
public class CreditAccount extends Account { … }

© JAA JMA 2015

@Entity(name = "DebitAccount")
@DiscriminatorValue(value = "Debit")
public class DebitAccount extends Account { … }

182

Página 80

Tabla por subclase
•

Requiere una tabla para la superclase con:
• Identificador común
• Propiedades de la clase base, comunes a todas sus subclases

•

Una tabla por cada subclase con:
• Identificador común
• Propiedades particulares de cada subclase

•

© JAA JMA 2015

•

Las tablas de subclase tienen asociaciones de clave principal a la tabla
de la superclase de modo que en el modelo relacional es realmente una
asociación uno-a-uno.
La implementación de Hibernate de tabla por subclase no requiere
ninguna columna discriminadora.

183






...



...



...



© JAA JMA 2015

Tabla por subclase

184

Página 81

Anotaciones para Tabla por subclases
@Entity(name = "Account")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Account { … }

@Entity(name = "DebitAccount")
@PrimaryKeyJoinColumn(name = "account_id")
public class DebitAccount extends Account { … }

© JAA JMA 2015

@Entity(name = "CreditAccount")
@PrimaryKeyJoinColumn(name = "account_id")
public class CreditAccount extends Account { … }

185

Tabla por clase concreta
•
•

Requiere una tabla por cada clase.
Si la superclase:

•
•

•
•

Cada tabla define columnas para todas las propiedades de la clase,
incluyendo las propiedades heredadas.
La limitación de este enfoque es que si una propiedad se mapea en la
superclase, el nombre de la columna debe ser el mismo en todas las
tablas de subclase.
La estrategia del generador de identidad no está permitida en la herencia
de unión de subclase.
La semilla de la clave principal (secuencia) tiene que compartirse a
través de todas las subclases unidas de una jerarquía.

© JAA JMA 2015

• es abstracta, hay que mapearla con abstract="true".
• no es abstracta, se necesita una tabla adicional para mantener las instancias
de la superclase.

186

Página 82






...


...


...



© JAA JMA 2015

Tabla por clase concreta

187

Anotaciones Tabla por clase concreta
@Entity(name = "Account")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Account { … }
@Entity(name = "DebitAccount")
public class DebitAccount extends Account { … }

© JAA JMA 2015

@Entity(name = "CreditAccount")
public class CreditAccount extends Account { … }

188

Página 83

@Any: Asociación polimórfica
public interface Property {
String getName();
T getValue();
}
@Entity
@Table(name="integer_property")
public class IntegerProperty implements Property { … }
@Entity
@Table(name="string_property")
public class StringProperty implements Property { … }
)
© JAA JMA 2015

@Any(metaDef = "PropertyMetaDef", metaColumn = @Column( name = "property_type" )
@JoinColumn( name = "property_id" )
private Property property;

189

© JAA JMA 2015

CONSULTAS CON HQL/JPQL

191

Página 84

HQL ( Hibernate Query Lenguage)
•

HQL es una de las 3 maneras que existen en Hibernate para realizar
consultas.
•

HQL (Hibernate Query Lenguage)
session.createQuery("from Category c where c.name like 'Laptop%'");
entityManager.createQuery("select c from Category c where c.name like 'Laptop%‘ ");

•

CRITERIA API
session.createCriteria(Category.class).add( Restrictions.like("name", "Laptop%") )

•

Direct SQL

© JAA JMA 2015

session.createSQLQuery("select {c.*} from CATEGORY {c} where NAME like 'Laptop%‘ ").addEntity("c",
Category.class);

193

HQL ( Hibernate Query Lenguage)
•

HQL es un lenguaje de consultas proporcionado por Hibernate
"Hibernate Query Language" .

•

HQL es muy parecido al SQL estándar, con la diferencia
fundamental de estar completamente orientado a objetos
•

•

Usamos nombres de clases y sus atributos en lugar de nombres de tablas y
columnas

Al ser orientado a Objetos podemos usar cosas como herencia,
polimorfismo y asociaciones.
Trabajamos realmente sobre las clase Java y es el Hibernate quien redacta las
consultas sobre las tablas mapeadas.

© JAA JMA 2015

•

194

Página 85

HQL ( Hibernate Query Lenguage)
•

Al trabajar sobre Java, debemos respetar la diferencia sintáctica
entre entre mayúsculas y minúsculas.
 Las clausulas como SELECT, FROM, etc, no distingue entre mayúsculas y minúsculas.
 Las Clases, Objetos y miembros si diferencian entre mayúsculas y minúsculas

•

HQL está diseñado exclusivamente para realizar la recuperación y
modificación de datos (DQL y DML).

•

La redacción de las consultas HQL es muy similar a las cláusulas
SELECT del lenguaje SQL.

SELECT u.username FROM Usuario u

© JAA JMA 2015

SELECT u.username FROM hql.modelo.Usuario u

195

HQL ( Hibernate Query Lenguage)
Características de HQL
Soporte completo para operaciones relacionales:



•

Devolución de resultados en forma de objetos:


•

Es muy similar a SQL estándar.

Soporte para características avanzadas:


•

Podemos declarar el resultado usando el tipo de la superclase y Hibernate se encargara de crear los objetos
adecuados de las subclases correctas de forma automática.

Fácil de Aprender:


•

Las consultas realizadas usando HQL devuelven los resultados de las mismas en la forma de objetos o listas de
objetos.

Consultas Polimórficas:


•

HQL permite representar consultas SQL en forma de objetos.
HQL usa clases y atributos o propiedades en vez de tablas y columnas.

HQL contiene muchas características avanzadas que son muy útiles (fetch joins, inner y outer joins), funciones de
agregación (max, avg), y agrupamientos, ordenación y subconsultas.

Es independiente del gestor de base de datos.

© JAA JMA 2015

•

196

Página 86

Consultas con HQL
•

Una consulta HQL debe ser preparada antes de ser ejecutada.

•

La preparación implica varios pasos:
1. Crear la consulta, con cualquier restricción arbitraria o proyección de los datos
que se desean recuperar.
2. Definición/Paso de variables BIND como parámetros de la Consulta, para poder
reutilizar la consulta posteriormente.
3. Ejecutar la consulta preparada contra la base de datos

•

Podemos controlar como se ejecuta la consulta y como se deben de devolver los
datos (de una vez o por partes, por ejemplo).

© JAA JMA 2015

4. Recuperar los datos.

197

Consultas con HQL
1.- Crear la consulta
•

Hibernate tiene el interfaz Query (org.hibernate.query) que nos da acceso a
todas las funcionalidades para poder leer objetos desde la base de datos.

•

Necesitamos crear una instancia de uno de estos objetos utilizando Session.

•

Para crear una nueva instancia de Hibernate Query, se invoca a uno de los
métodos CreateQuery () en Session.
Query query = session.createQuery("SELECT p.nombre FROM Profesor p");
Query query = session.createQuery("FROM Profesor");

•

Hasta este momento no se ha enviado nada a la BBDD sólo se ha creado la
consulta.
en mysql
© JAA JMA 2015

("FROM Profesor"); → Select *

198

Página 87

Consultas con HQL
1.- Crear la consulta
•

La clausula FROM
 Es la clausula más simple que existe en Hibernate y la única obligatoria.
 Esta clausula devuelve todos las filas de la tabla indicada que se encuentran en la base
de datos.
FROM hql.modelo.Usuario

o

FROM Usuario

 Si ponemos mas de una Clase, haremos un producto cartesiano
FROM Profesor, Asignatura
FROM Profesor LEFT JOIN Asignatura

•

Necesitamos crear ALIAS en las clases para poder hacer referencia a las
propiedades de la clase, sino → Excepcion.
→ Excepction
→ OK
© JAA JMA 2015

FROM Profesor where Profesor.Id=12;
FROM Profesor p where p.Id=12;

200

Consultas con HQL
1.- Crear la consulta
•

La clausula WHERE
 Es la clausula permite el filtrado de la consulta.
 Los literales se encierran entre apostrofes (comillas simples)

•

La expresión acepta operadores:







De comparación: = != <> > >= < <= BETWEEN LIKE IN IS NULL
Lógicos: AND OR NOT
Aritméticos: + - * /
Concatenacion: ||
Colecciones: SIZE IS EMPTY IS NOT EMPTY MINELEMENT MAXELEMENT
Subconsultas

•

Dispone de funciones sobre escalares:
 UPPER LOWER CONCAT TRIM SUBSTRING LENGTH ABS SQRT MOD …

© JAA JMA 2015

FROM Profesor p WHERE p.nombre='ANTONIO' AND p.ape1 LIKE 'LAR%'

201

Página 88

Consultas con HQL
1.- Crear la consulta
•

Agrupaciones
 Al igual que en SQL se pueden realizar agrupaciones mediante las palabras claves
GROUP BY y HAVING
 Las funciones de agregación que soporta HQL son:
– COUNT SUM AVG MIN MAX
FROM Profesor p WHERE p.ape1 LIKE 'LAR%' GROUP BY p.nombre HAVING count(p.nombre)>2

•

La clausula ORDER BY
 También es posible ordenar los resultados como en SQL.

© JAA JMA 2015

FROM Profesor p ORDER BY p.nombre, p.ape1 DESC

202

Consultas con HQL
1.- Crear la consulta
•

Paginando resultados
 Cuando realizamos una consulta podemos especificar el número máximo de filas a
recuperar, mediante el método query.setMaxResults( N );
Query query = session.createQuery("FROM Profesor");
Query.setMaxResults(10);
Sólo se recuperarán las 10 primeras filas

 También podemos indicar que valor nos interesa de los recuperados mediante el
método query.setFirstResult( N );

→ De los 10 resultados devueltos, solo se tratan a partir del 2

Los elementos se enumeran desde 0
Query query = session.createQuery(".......");
query.setMaxResults(tamanyoPagina);
query.setFirstResult(paginaAMostrar * tamanyoPagina);

© JAA JMA 2015

query.setMaxResults(10);
query.setFirstResult(2);

203

Página 89

Consultas con HQL
2.- Paso/Definición de variables BIND
•

Cuando necesitemos crea una sentencia DINAMICA, deberemos utilizar variables
BIND para evitar SQL Inyection.

•

Nunca deberemos escribir sentencias como adición de textos
String queryString =“ from Item i where i.description like ‘ “ + search + “ ‘ “ ;
Search = ‘ uno or 1=1 ‘

•

La forma correcta de reescritura de esta consulta sería mediante la utilización de
parámetros con nombre

Query q = session.createQuery ( queryString ).setString ("search", ‘valor’);
.setDate("search", ‘valor’);
.setInteger("search", ‘valor’);
.setParameter("search", ‘valor’);

© JAA JMA 2015

String queryString =“ from Item i where i.description like :search“ ;

204

Consultas con HQL
3y4.- Ejecución de la consulta y recuperación de datos
•

Una vez que hayamos creado y preparado una consulta, ya estamos listos para
para ejecutarlo y recuperar el resultado en la memoria.

•

Para recuperar todo el resultado de una sola vez, utilizaremos el método
query.list().

•

El método query.list() ejecuta la sentencia y devuelve el resultado como un
objeto java.util.List.
Query query = session.createQuery("FROM Profesor");
List  profesores = query.list();

Nos devolverá una Lista de instancias de Profesor donde después deberemos
tratar las propiedades que deseemos.
© JAA JMA 2015

•

205

Página 90

Consultas con HQL
3y4.- Ejecución de la consulta y recuperación de datos
•

HQL también permite que las consultas devuelvan datos escalares en vez de
objetos completos.
 SELECT p.id, p.nombre FROM Profesor p

•

La anterior consulta devolverá el código y el nombre del profesor en vez del
Objeto profesor.

•

En estos casos el método list() retorna una lista de Arrays de objetos, un array
por fila de resultados con tantos elementos como propiedades hayamos definido
en la SELECT.

for (Object[] datos : listDatos) {
System.out.println(datos[0] + "--" + datos[1]);
}

© JAA JMA 2015

Query query = session.createQuery("SELECT p.id, p.nombre FROM Profesor p");
List listDatos = query.list();

206

Consultas con HQL
3y4.- Ejecución de la consulta y recuperación de datos
•

Si en vez de recuperar varias columnas, SOLO se recupera una
 SELECT p.nombre FROM Profesor p

•

En estos casos el método list() retorna una Lista de objetos
Query query = session.createQuery("SELECT p.nombre FROM Profesor p");
List listDatos = query.list();

© JAA JMA 2015

for (Object datos : listDatos) {
System.out.println(datos);
}

207

Página 91

Consultas con HQL
3y4.- Ejecución de la consulta y recuperación de datos
•

Resultados Únicos
 En muchas ocasiones una consulta únicamente devolverá cero o un resultado.
 En ese caso es poco práctico que nos devolver un conjunto de elementos, cuando sólo
vamos a recuperar un único elemento.
 Para facilitarnos dicha tarea Hibernate dispone del método query.uniqueResult().
 Este método sólo se debe de utilizar cuando estemos seguro que sólo nos devolverá 1
registro.

© JAA JMA 2015

Query query = session.createQuery("FROM Profesor where ……..");
Profesor profesor = query.uniqueResult();

208

•

Para facilitar la mantenibilidad del software, las consultas a base de
datos no deberían escribirse directamente en el código sino que
deberían estar en un fichero externo para que puedan modificarse
fácilmente.

•

Hibernate provee una funcionalidad para hacer esto mismo de una
forma sencilla denominada «consultas con nombre».

•

Esto lo podemos realizar, añadiendo el TAG  en el fichero
de mapeo correspondiente a la Clase.

•

En JPA se realizaría mediante la anotación @NamedQuery:
@Entity
@NamedQuery(name="Profesor.findAll", query="SELECT p FROM Profesor p")
public class Profesor { … }

© JAA JMA 2015

Consultas con Nombre

209

Página 92

Consultas con Nombre
•

Este mapeo deberá contener:
•
•

NOMBRE que posteriormente utilizaremos en el código de Hibernate.
CONSULTAR a ejecutar posteriormente.

Profesor.hbm.xml





TAG 
name
Nombre de la consulta que posteriormente
utilizaremos en código Java

Indicación XML para indicar el fin de la consulta

:
Query query =
session.getNamedQuery("TodosLosProfesores");
:

© JAA JMA 2015











210

Recuperación
•

Las diferentes estrategias de recuperación se dividen por:
• Cuando:
 EAGER (la segunda selección se emite inmediatamente)
 LAZY (la segunda selección se retrasa hasta que se necesitan los datos)

• Como:
 SELECT: Realiza una selección SQL separada para cargar los datos. Esta es la estrategia
generalmente denominada N + 1.
 JOIN: Inherentemente un estilo de recuperación EAGER. Los datos que se van a recuperar se
obtienen mediante el uso de una unión externa SQL.
 BATCH: Realiza una selección de SQL separada para cargar una cantidad de elementos de
datos relacionados utilizando una restricción de IN como parte de la cláusula WHERE de SQL
basada en un tamaño de lote.
 SUBSELECT: Realiza una selección de SQL por separado para cargar los datos asociados en
función de la restricción de SQL utilizada para cargar el propietario.

• Donde: (Ámbito de definición)

– HQL / JPQL
– Perfiles de búsqueda
– Grafos de entidades

© JAA JMA 2015

 Estático: Definidas declarativamente en el mapeo.
 Dinámico:

211

Página 93

Optimización de HQL
•

Uno de los mayores problemas que nos podemos encontrar al usar
un ORM es la lentitud que puede tener respecto a una aplicación
realizada directamente con JDBC.

•

Con JDBC determinamos cuantas instrucciones SQL lanzamos y
como optimizarlas.

•

Desde Hibernate, inicialmente, no podemos hacerlo ya que es
Hibernate el que se encarga de realizar todas las SQL por nosotros.

•

Hay 2 situaciones que debemos atender:
© JAA JMA 2015

 Lazy Load: "n+1" SELECTs
 Consultas nativas

212

Optimización de HQL
"n+1" SELECTs
•

Es uno de los mayores problemas del ORM.

•

Este problema consiste en que al lanzar un consulta con HQL que retorna n filas,
el ORM lanza n+1 consultas SQL de SELECT.

•

Cuando tenemos un registro (profesor) que tiene varios registros asociados (correos),
se lanza una consulta por cada correo devuelto.

•

Suelen aparecer cuando estamos tratando Asociaciones:
 1aN
 NaM

Ejecutando lo siguiente:
© JAA JMA 2015

•

213

Página 94

Optimización de HQL
"n+1" SELECTs
public class Profesor implements Serializable {
private int id;
private String nombre;
private String ape1;
private String ape2;
private Set correosElectronicos;
:

public class CorreoElectronico implements Serializable {
private int idCorreo;
private String direccionCorreo;
private Profesor profesor;
:

© JAA JMA 2015

:
Query query = session.createQuery("SELECT p FROM Profesor p");
List profesores = query.list();
for (Profesor profesor : profesores) {
System.out.println(profesor.toString());
for (CorreoElectronico correoElectronico : profesor.getCorreosElectronicos()) {
System.out.println("\t"+correoElectronico); }
}

214

Optimización de HQL
"n+1" SELECTs
•

El lenguaje SQL ESTANDAR no permite consultas jerárquicas.

•

La consulta anterior devuelve todos los profesores con todos los correos, repitiendo el
profesor tantas veces como correos tenga.

•

Hibernate no elimina esa duplicidad así que debemos hacerlo explícitamente desde
Java.

•

Para evitar la duplicación desde la consulta se dispone de distinct:

© JAA JMA 2015

Query query = session.createQuery(
"SELECT DISTINCT p FROM Profesor p LEFT JOIN FETCH p.correosElectronicos");
List  profesores = query.list();

215

Página 95

Optimización de HQL
Consultas Nativas
•

Otra forma de optimizar las consultas es realizando Consultas Nativas
directamente desde Hibernate.

•

Pueden ser utilizadas para aprovechar las características propias de la Base de
Datos ( hints, órdenes propias (top, NVL, etc), procedimientos almacenados, etc)

•

La ejecución de consultas SQL nativas se controla por medio de la interfaz
SQLQuery, la cual se obtiene llamando a Session.createSQLQuery().

•

Este tipo de consulta puede devolver 2 tipos de elementos:
 Valores CRUDOS/escalares básicos

© JAA JMA 2015

 Objetos de Entidades Mapeadas en Hibernate

216

Optimización de HQL
Consultas Nativas
• Valores CRUDOS/escalares básicos
 Son valores independientes.
 Se devolverá una lista de objetos arrays (Object[]) con valores escalares para cada
columna en la tabla
Query sqlQuery = Session.createSQLQuery("SELECT * FROM PROFESOR");
sqlQuery.list();
 Podemos especificar las columnas de forma predeterminada
Query sqlQuery = Session.createSQLQuery("SELECT ID, nombre FROM
PROFESOR");

Query sqlQuery = Session.createSQLQuery("SELECT * FROM PROFESOR")
.addScalar("ID", Hibernate.LONG)
.addScalar("NOMBRE", Hibernate .STRING);

© JAA JMA 2015

O indicando el tipo de Hibernate a devolver

217

Página 96

Optimización de HQL
Consultas Nativas
• Objetos de Entidades Mapeadas en Hibernate
 La otra forma de trabajar con las consultas Nativas y es que devuelvan los datos como
objetos de Entidades mapeadas en Hibernate.
 Utilizaremos el método addEntity para obtenerlos
 La siguiente orden devolverá una Lista en donde cada elemento es un objeto de la
entidad mapeado

Query sqlQuery = Session.createSQLQuery("SELECT ID, Nombre FROM
PROFESOR").addEntity(Profesor.class);
sqlQuery.list();

© JAA JMA 2015

Query sqlQuery = Session.createSQLQuery("SELECT * FROM
PROFESOR").addEntity(Profesor.class);
sqlQuery.list();

218

@Fetch
•

Además de las anotaciones JPA FetchType.LAZY o FetchType.EAGER,
también se puede usar la anotación @Fetch específica de Hibernate que
acepta uno de los siguientes FetchMode(s):
• SELECT (Es equivalente a la estrategia de obtención FetchType.LAZY)
 La asociación se buscará perezosamente utilizando una selección secundaria para
cada entidad individual, colección o carga de unión.

• JOIN: (Es equivalente a la estrategia de obtención FetchType.EAGER)
 Utiliza una combinación externa para cargar las entidades, colecciones o uniones
relacionadas cuando se utiliza la obtención directa. de JPA.

• SUBSELECT

@OneToMany(mappedBy = "region", fetch = FetchType.LAZY)
@Fetch(FetchMode.SUBSELECT)
private Set countries;

© JAA JMA 2015

 Disponible solo para colecciones. Se utiliza un segundo SELECT para recuperar
las colecciones asociadas de todas las entidades recuperadas en una consulta o
recuperación previa. A menos de que deshabilite explícitamente la recuperación
perezosa, esta segunda selección sólo se ejecutará cuando se acceda a la
asociación. Una consulta por tabla.

219

Página 97

@BatchSize
•

Usando la recuperación por lotes, Hibernate puede cargar varios proxies
sin inicializar si se accede a un proxy (lectura anticipada). La
recuperación en lotes es una optimización de la estrategia de
recuperación por selección perezosa.

•

A nivel de entidad:
@Entity
@BatchSize(size = 5)
public class Profesor implements Serializable { … }

A nivel de colección:
@OneToMany(mappedBy = "region", fetch = FetchType.LAZY)
@BatchSize(size = 5)
private Set countries;

© JAA JMA 2015

•

220

Dinámico: Perfiles de búsqueda
•

Permiten sustituir dinámicamente las definiciones estáticas.
@FetchProfile(
name = "region.all",
fetchOverrides = {
@FetchProfile.FetchOverride(
entity = Region.class, association = "countries", mode = FetchMode.JOIN
),
@FetchProfile.FetchOverride(
entity = Country.class, association = "locations", mode = FetchMode.JOIN
)
}
)
public class Region { … }

Para utilizar el perfil se asocia a la sesión:
© JAA JMA 2015

•

221

Página 98

Dinámico: Grafos de entidades
•

Se pueden configurar diferentes grafos de recuperación (grafo de
componentes y atributos que cargar) y seleccionar dinámicamente cual
utilizar en la consulta. Pueden anular una asociación de recuperación de
LAZY.
@NamedEntityGraph(name = "region.countries+locations",
attributeNodes = @NamedAttributeNode(
value = "countries", subgraph = "region.countries.locations"),
subgraphs = @NamedSubgraph(
name = "region.countries.locations",
attributeNodes = @NamedAttributeNode("locations")))
public class Region { … }

Para utilizar un grafo en una consulta:
Region region = em.find(Region.class, 1L, Collections.singletonMap("javax.persistence.fetchgraph",
em.getEntityGraph("region.countries+locations");
));
List rslt = em.createQuery("from Region")
.setHint("javax.persistence.fetchgraph", em.getEntityGraph("region.countries+locations"))
.getResultList();

© JAA JMA 2015

•

222

Consultas de solo lectura
Al igual que la inmutabilidad de entidades, la obtención de entidades en
modo de solo lectura es mucho más eficiente que la obtención de entidades
de lectura-escritura.
List rslt = entityManager.createQuery(" … ", Profesor.class )
.setHint( "org.hibernate.readOnly", true )
.getResultList();

@NamedQuery(
name = "get_read_only_profesores",
query = "select p from Profesor",
hints = { @QueryHint(name = "org.hibernate.readOnly", value = "true“) }
)

© JAA JMA 2015

También se puede pasar la sugerencia de solo lectura a las consultas con
nombre usando la anotación @QueryHint de JPA.

223

Página 99

DML con HQL
•

También podemos realizar operaciones DML con HQL

•

Deberemos utilizar el método executeUpdate del objeto session.
session.beginTransaction();
session.createQuery("update Profesor p set p.nombre=UPPER(p.nombre) ").executeUpdate();
session.getTransaction().commit();

© JAA JMA 2015

session.beginTransaction();
session.createQuery("delete from Profesor p where p.id=8").executeUpdate();
session.getTransaction().commit();

226

Procesamiento por lotes
•

Inserciones masivas de datos son operaciones que NO deben de ser
realizadas a través de Hibernate.
•

Por ejemplo, un usuario puede tener 100.000 registros que tienen que ser
importados en una sola tabla.

•
•

Este código podría generar una excepcion OutOfMemoryException.
Hibernate mantiene en caché todas las instancias recién insertadas a nivel de
sesión.

© JAA JMA 2015

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
}
tx.commit();
session.close();

227

Página 100

•

Si se puede es mejor realizarlo de forma externa o mediante JDBC
con operaciones BULK.

•

Si, por alguna razón, debemos de hacer la importación masiva a
través de Hibernate, deberemos tener en cuenta unas
recomendaciones:
•

Utilización de hibernate.jdbc.batch_size

•

Utilizar Session.flush() y Session.clear() regularmente

•

Considerar la utilización de Session.commit;

•

Utilizar una Session sin estado

© JAA JMA 2015

Procesamiento por lotes

228

Procesamiento por lotes
Utilización de hibernate.jdbc.batch_size
•

La primera recomendación para un procesamiento masivo de filas (batch
processing), es habilitar el uso del lote JDBC.

•

Deberemos de introducirlo dentro del fichero de configuración de Hibernate
(hibernate.cfg.xml)

•

El valor recomendable es entre 10 y 50

•

Este valor sólo se debe de indicar cuando estemos seguro que una transacción
realiza Inserciones/Actualizaciones de filas en conjunto.

•

El valor a definir sería el mayor número de filas que intervienen en una operación
DML.

© JAA JMA 2015

20

229

Página 101

Procesamiento por lotes
Utilizar Session.flush() y Session.close();
•

La utilización de Session.flush() o Session.close () permite controlar la memoria
cache de la Session.

•

Hibernate "limpia" (Flush) la memoria de la Session, de forma automática,
después de la realización de una transacción.

•

Session.flush()
 Fuerza la sincronización entre la Memoria de la Session y la Base de Datos, es decir, obliga a escribir
los cambios en la BBDD

•

Session.clear()

© JAA JMA 2015

 Fuerza la eliminación de las diferentes instancias creadas/modificadas que están en la Memoria de la
Session

230

Procesamiento por lotes
Utilizar Session.flush() y Session.close();
•

Al hacer persistentes los objetos nuevos, es necesario que realice flush() y luego
clear() en la sesión regularmente para controlar el tamaño del caché de primer
nivel.

© JAA JMA 2015

for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) {
session.flush();
session.clear();
}
}

231

Página 102

Procesamiento por lotes
Desplazamiento de sesión
Además se deberia utilizar el método scroll() para aprovechar los cursores del
lado del servidor para las consultas que devuelven muchas filas de datos.
ScrollableResults scrollableResults = null;
try {
em = emf.createEntityManager();
em.getTransaction().begin();
scrollableResults = em.unwrap(Session.class).createQuery("from Person")
.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
int batchSize = 25; int count = 0;
while (scrollableResults.next()) {
processPerson((Person) scrollableResults.get(0));
if (++count % batchSize == 0) { em.flush(); em.clear(); }
}
em.getTransaction().commit();
} catch (RuntimeException e) {
if (em.getTransaction().isActive()) em.getTransaction().rollback();
throw e;
} finally {
if (scrollableResults != null) scrollableResults.close();
if (em != null) em.close();
}

© JAA JMA 2015

•

232

Procesamiento por lotes
Considerar la utilización de Session.commit;
•

Podemos utilizar Session.commit para validar la transacción por partes en vez de
realizarla de forma completa.

•

Ventajas
 Grabación de datos ante posibles caídas de BBDD/Aplicación, etc.
 Liberación de memoria Cache de la Session.

•

Inconvenientes

for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { session.commit; }
}

© JAA JMA 2015

 Deberemos estar seguro que la transacción se puede validar por partes y no de forma
completa.

233

Página 103

Procesamiento por lotes
StatelessSession es una API orientada a comandos proporcionada por Hibernate para
transmitir datos hacia y desde la base de datos en forma de objetos separados sin un
contexto de persistencia asociado y no proporciona muchas de las semánticas de ciclo
de vida de nivel superior.
statelessSession = emf.unwrap( SessionFactory.class).openStatelessSession();
statelessSession.getTransaction().begin();
scrollableResults = statelessSession
.createQuery( "select p from Person p" )
.scroll(ScrollMode.FORWARD_ONLY);
while ( scrollableResults.next() ) {
processPerson((Person) scrollableResults.get( 0 ));
statelessSession.update( Person );
}
statelessSession.getTransaction().commit();
} catch (RuntimeException e) {
if (statelessSession.getTransaction().getStatus() == TransactionStatus.ACTIVE)
statelessSession.getTransaction(). rollback();
throw e;
} finally {
if (scrollableResults != null) scrollableResults.close();
if (statelessSession != null) statelessSession.close();
}

© JAA JMA 2015

try {

234

Personalización de DML
•

Hibernate nos da la posibilidad de indicarle en su fichero de
configuración el modelo de orden DML que se ejecutará.

•

Esto nos permite añadir elementos adicionales propios del gestor.

•

El fichero de mapeo de Hibernate puede incluir los siguientes tags
para especificarlo

Hibernate.cfg.xml

Contiene una sql de INSERT
Contiene una sql de UPDATE
Contiene una sql de DELETE

:
 INSERT INTO Profesor (Nombre,Ape1,Ape2,Id) VALUES (?,?,?,?)
UPDATE Profesor SET Nombre=?,Ape1=?,Ape2=? WHERE Id=? 
 DELETE FROM Profesor WHERE Id=?


© JAA JMA 2015

 :
 :
 :

235

Página 104

Personalización de DML
•

Al ser definiciones SQL Nativas se podría usar cualquier
característica especifica que necesitemos de la base de datos que
estemos usando.
Hibernate.cfg.xml
:
 INSERT /*+ APPEND */ INTO Profesor (Nombre,Ape1,Ape2,Id) VALUES (?,?,?,?)
UPDATE /*+ NO_INDEXES */ Profesor SET Nombre=?,Ape1=?,Ape2=? WHERE Id=? 
 DELETE FROM Profesor WHERE Id=?


•

Cuando realicemos una orden DML, nos aparecerá algo similar a:

•

JPA dispone de sus propias anotaciones @SQLInsert,
@SQLUpdateY @SQLDelete para anular el INSERT, UPDATE,
DELETE de una entidad determinada.

© JAA JMA 2015

Hibernate: INSERT /*+ APPEND */ INTO Profesor (Nombre,Ape1,Ape2,Id) VALUES (?,?,?,?)
Hibernate: UPDATE /*+ NO_INDEXES */ Profesor SET Nombre=?,Ape1=?,Ape2=? WHERE Id=?
Hibernate: DELETE FROM Profesor WHERE Id=?

236

Uso de procedimientos almacenados
Hibernate proporciona soporte para consultas a través de procedimientos y
funciones almacenados.
• Los argumentos de un procedimiento almacenado se declaran utilizando el
modo de parámetro IN, el resultado puede marcarse con el modo OUT, un
REF_CURSOR o simplemente podría devolver el resultado como una
función.

List list = entityManager.createStoredProcedureQuery( "sp_phones")
.registerStoredProcedureParameter( 1, Long.class, ParameterMode.IN)
.setParameter(1, 1L)
.getResultList();

© JAA JMA 2015

StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "sp_calc_value")
.registerStoredProcedureParameter( "personId", Long.class, ParameterMode.IN);
.registerStoredProcedureParameter( “rslt", Long.class, ParameterMode.OUT)
.setParameter("personId", 1L)
.execute();
Long value = (Long) query.getOutputParameterValue(“rslt");

238

Página 105

© JAA JMA 2015

API DE CRITERIA

239

Introducción
•

Criteria API es una alternativa poderosa y elegante a HQL.

•

Está especialmente diseñado para las funcionalidades de búsqueda
WEB dinámica donde las consultas se hacen ‘online’.
 Casillas de Verificación
 Campos de entrada
 Cambios de Usuarios.

JPA no soporta Criteria API.

•

Criteria permite crear consultas en programación mediante la
creación y combinación de objetos en el orden correcto.
© JAA JMA 2015

•

241

Página 106

Introducción
•

Criteria permite utilizar filtros y condiciones lógicas para la
construcción de la consulta.

•

La interfaz Session proporciona un método createCriteria () para
trabajar con objetos Criteria.

•

Enfoque HQL:
•

la implementación de una consulta HQL multi-criterios implica la construcción de
la misma en base a los criterios de búsqueda introducidos por el usuario.
queryBuf.append (firstClause "dónde": "y");
queryBuf . append ("s.date> =: startDate");
queryBuf.append (firstClause "dónde": "y ");
:

Criteria Criterios = session.createCriteria (Sale.class);
if (startDate! = null) { criteria.add (Expression.ge ("fecha", startDate); } i
f (endDate! = null) { criteria.add (Expression.le ("fecha", endDate); }

© JAA JMA 2015

• Enfoque Criteria:

242

Creación de objetos Criteria
•

La interfaz Session proporciona un método createCriteria () que
puede ser utilizado para crear un objeto Criteria.

•

El objeto creado, podrá devolver todas las instancias de la clase
especificada cuando ejecutemos la sentencia (list).

•

Podemos crear objetos Criteria sin tener una Session; utilizaremos la
clase DetachedCriteria para hacerlo y posteriormente añadirlo a una
Session.
DetachedCriteria crit = DetachedCriteria.forClass(User.class)
:
List result = crit.getExecutableCriteria(session).list();

© JAA JMA 2015

Criteria criteria = session.createCriteria(Profesor.class);

243

Página 107

Creación de objetos Criteria
•

Una vez creado el objeto Criteria, procederemos a filtrar/configurar
nuestra consulta.

•

Podemos
•
•
•

Podemos añadir todas las restricciones/filtros que deseemos,
siempre y cuando sean compatibles entre ellas.

© JAA JMA 2015

•

Añadir restricciones mediante el método .add(Expresion)
Utilizar métodos para devolución de un número máximo de valores o sólo las N
primeras instancias.
Realizar ordenaciones en la obtención de datos

244

Gestión de objetos Criteria
•

Ordenaciones
•

El API de Criteria proporciona la clase org.hibernate.criterion.Order para ordenar su
conjunto de resultados, de acuerdo con una de las propiedades de su objeto.

•

Esta ordenación se hace en el mismo momento de realizar la ejecución de la consulta.

•

Utilizaremos el método criteria.addOrder(….)
 criteria.addOrder ( tipo_ordenacion (Columna) )
criteria.addOrder ( Order.desc ( "Fecha" ) );

•

Ninguna instancia ha sido devuelta aún.

© JAA JMA 2015

session.createCriteria(Profesor.class).addOrder(Order.asc("ape1")).addOrder(Order.asc("ape2") );

245

Página 108

Gestión de objetos Criteria
•

Paginación
•

El API de Criteria define 2 métodos para acotar la devolución de resultados:

•

setFirstResult(int PrimeraFila)
 El número entero (PrimeraFila) define cual es la primera instancia a devolver.
 El valor comienza desde 0.

•

setMaxResults(int maxResults)

Criteria cr = session.createCriteria(Profesor.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
:
List results = cr.list();
// Devuelve 10 resultados desde la instancia segunda (1)

© JAA JMA 2015

 maxResults indica a Criteria cual es el número máximo de instancias a devolver.

246

Gestión de objetos Criteria
•

Varios
•

setCacheable ( boolean)
 Habilitar el almacenamiento en caché de este resultado de la consulta, si la caché de consultas
está activada.

•

uniqueResult()
 Obliga a la consulta a devolver una sola instancias que coincida con la petición de la consulta.
 Si la consulta no devuelve ningún resultado → NULL.

•

setTimeout(int timeout)

© JAA JMA 2015

 Configura un tiempo máximo de espera para la consulta JDBC.

247

Página 109

Objetos Criteria. Expresiones
Expresiones
•

El API de Criteria proporciona la clase org.hibernate.criterion.Restrictions la cual define
métodos para incorporar Restricciones más específicas a nuestra consulta.

•

Disponemos restricciones referentes a:









•

Operadores estándar SQL ( =, <,<= >, >=) eq(), lt(), le(), gt(), ge()
isNull, isNotNull
isEmpty, isNotEmpty
Or
Between
Like
In
eqProperty, ltProperty, gtProperty

Estas restricciones pueden ser añadidas al objeto CRITERIA en base a:
 Mediante la creación de un objeto CRITERION
 Directamente al objeto Criteria.

© JAA JMA 2015

•

248

Objetos Criteria. Expresiones
•

Expresiones. Objeto CRITERION
•

La creación de un Objeto CRITERION, permite la definición de una restricción que
puede ser utilizar en 1 o en varios objetos Criteria.

•

Deberemos crearlo siguiendo la sintaxis:
 Criterion restriction = Restrictions.XXXXXX

•

Una vez creado, podemos asignárselo al objeto Criteria que elijamos mediante el
método .add(objeto_criterion)
Criterion restriction = Restrictions.between("amount",new BigDecimal(100), new BigDecimal(200) );

© JAA JMA 2015

Criteria cri = session.createCriteria(Bid.class);
cri.add(restriction);

249

Página 110

Objetos Criteria. Expresiones
•

Expresiones. Directamente en Criteria
•

Si la restricción que vamos a crear sólo se aplica a un objeto Criteria, no es necesario
la creación de un objeto CRITERION.

•

Podemos crear la restricción de forma online aplicando dicha restricción en el
momento.
Criteria cri = session.createCriteria(Bid.class);
cri.add ( Restrictions.between("amount",new BigDecimal(100), new BigDecimal(200) );

Esta forma de aplicar restricciones crear un Objeto CRITERION sin referencia y sólo se
puede utilizar en esta asignación.

© JAA JMA 2015

•

250

Objetos Criteria. Expresiones
Expresiones. Operadores estándar SQL
•

Podemos utilizar los operadores estándar de SQL( =, <,<= >, >=), pero debemos de
utilizarlos en formato texto y no el símbolo
Símbolo

Operador

Igual

Operación

=

eq()

Menor que

<

lt()

<=

le()

Menor o igual
Mayor que
Mayor o igual

•

>

gt()

>=

ge()

Estos operadores están disponibles como métodos del objeto Restrictions (Expression
deprecated) y lo añadimos mediante el método .add al objeto Criteria
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.XX ("COLUMNA", VALOR ) );

© JAA JMA 2015

•

251

Página 111

Objetos Criteria. Expresiones
•

Expresiones. Operadores estándar SQL
•

EJEMPLOS
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.gt("salary", 2000));
// Registros cuyo salario sea mayor que 2000
cr.add(Restrictions.lt("salary", 2000));
// Registros cuyo salario sea menor que 2000
cr.add(Restrictions.eq("fecha", new Date() ));
// Registros cuya fecha sea igual a la actual

© JAA JMA 2015

cr.add(Restrictions.eq("Nombre", "Jose" ));
// Registros cuya nombre sean Jose

252

Objetos Criteria. Expresiones
•

Expresiones. isNull, iSNotNull, isEmpty, isNotEmpty
•

Para hacer el tratamiento de las columnas nulas o no Nulas de las Base de datos
disponemos de las restricciones isNull y isNotNull

•

Para conocer si un elemento está vacío o no, disponemos de isEmpty y isNotEmpty
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.isNull("salary"));
cr.add(Restrictions.isNotNull("salary"));

cr.add(Restrictions.isNotEmpty("salary"));

© JAA JMA 2015

cr.add(Restrictions.isEmpty("salary"));

253

Página 112

Objetos Criteria. Expresiones
•

Expresiones. Or
•

Podemos crear expresiones lógicas OR y AND

•

Debemos realizar 2 pasos
1.
2.

Crear los objetos CRITERION para realizar de forma correcta la comparativa.
Crear un objeto LogicalExpresion para agrupar la Expresión Lógica

Criteria cr = session.createCriteria(Employee.class);
Criterion salary = Restrictions.gt ("salary", 2000);
Criterion dept1 = Restrictions.eq ("dept", 10);

Creación de los objetos para
luego hacer las comparaciones

LogicalExpression orExp = Restrictions.or(salary, dept1);

Equivalente a

=>

Añadir la Restricción

where salary > 2000 or dept=10

© JAA JMA 2015

cr.add( orExp );

Creación de LogicalExpression y
aplicación de OR

254

Objetos Criteria. Expresiones
•

Expresiones. Or
•

Podemos crear expresiones lógicas OR y AND

•

También podemos definir las expresiones lógicas de la siguiente forma:
Criteria cr = session.createCriteria(Employee.class);

© JAA JMA 2015

cr.add( Restrictions.or(
Restrictions.and(
Restrictions.like("firstname", "G%"),
Restrictions.like("lastname", "K%")
),
Restrictions.in("email", emails)
)

255

Página 113

Objetos Criteria. Expresiones
•

Expresiones. Between, Like e IN
•

También disponemos de la posibilidad de añadir restricciones de rangos (BETWEEN),
patrones de búsqueda (LIKE) y valores concretos dentro de listas (IN)
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.like ("Nombre" , "J%" ));
cr.add(Restrictions.between ("Salario" , 1000, 2000 ));
cr.add(Restrictions.between ("Salario" , new BigDecimal(100), new BigDecimal(200) ));
cr.add(Restrictions.between ("Fecha" , FechaInicial, new Date() ));

© JAA JMA 2015

String[] emails = { "foo@hibernate.org", "bar@hibernate.org" };
cr.add(Restrictions.in ("CorreoElectronico" , emails ));

256

Objetos Criteria. Expresiones
•

Expresiones. eqProperty, ltProperty, gtProperty
•

También tenemos la posibilidad de comparar 2 propiedades determinadas, mediante
los métodos:
 eqProperty, ltProperty, gtProterty
Criteria cr = session.createCriteria(Employee.class);
cr.add ( Restrictions.eqProperty("firstname", "username") )

© JAA JMA 2015

cr.add ( Restrictions.ltProperty("FechaExamen", "FechaAcceso") )

257

Página 114

sqlRestriction
•

La API de Criteria no tiene un equivalente a las funciones SQL nativas como
LENGTH (), UPPER, LOWER, etc

•

Criteria puede añadir este tipo de restricciones añadiendo Restricciones
especiales tipo Restrictions.sqlRestriction.
Criteria cr = session.createCriteria(Employee.class);
cr..add( Restrictions.sqlRestriction (" length ( {alias}.PASSWORD ) < 5 ");

// v4.2 sup

cr..add( Restrictions.sqlRestriction (
" length ( {alias}.PASSWORD ) < ? ", 5, Hibernate.INTEGER );
" length ( {alias}.PASSWORD ) < ? ", 5, org.hibernate.type.StandardBasicTypes.INTEGER);
{alias}
→ Employee
?
→ Variable Bind que es sustituido por 5
Hibernate.INTEGER → Especifica el tipo del parámetro utilizado

© JAA JMA 2015

// v3.6-v4.1

259

sqlRestriction
•

Este tipo de configuración, es también utilizado para la creación de
subconsultas dentro de una restricción
Criteria cr = session.createCriteria(Employee.class);

© JAA JMA 2015

cr..add( Restrictions.sqlRestriction (
" ‘salary' > all" +
" ( select b.AMOUNT from BID b where b.ITEM_ID = {alias}.ITEM_ID )“
)

260

Página 115

Varios
•

Además de todo lo anterior, la API de Criteria puede realizar operaciones
de:
•

Especificar restricciones en entidades relacionadas (1aN)
 Definir una Restricción en una tabla (1) y a la vez crear una Restricción en la Tabla Relacionada (N)

•

Recuperación dinámica de Asociaciones mediante setFetchMode().
 Cuando recuperamos la principal, podemos a la vez recuperar todas las colecciones asociadas a la
principal.
 Seria como realizar un JOIN entre ambar tablas
.setFetchMode("profesor", FetchMode.EAGER)

•

Proyecciones, agregación y agrupamiento.
 Nos permite obtener Funciones de Agrupamiento (SUM, AVG, MAX, ROWCOUNT) de la tabla

principal

 Sólo podemos definir una por operación

© JAA JMA 2015

.setProjection( Projections.rowCount() )
.setProjection( Projections.avg(" salary " ) )
.setProjection( Projections.max(" salary " ) )

CICLO DE VIDA CON OBJETOS
DE ENTIDAD

© JAA JMA 2015

261

264

Página 116

Introducción al ciclo de vida
•

Hibernate utiliza un mecanismo transparente de persistencia y
también una gestión optimizada de los objetos involucrados en ellos.

•

Si entendemos el ciclo de vida de los objetos, podremos afinar más
nuestras aplicaciones.

•

Cualquier aplicación con persistente debe interactuar con el servicio
de persistencia (Hibernate) cada vez que necesita propagar el
estado que tiene en la memoria a la base de datos (o viceversa).

BBDD

© JAA JMA 2015

Memoria

266

Introducción al ciclo de vida
•

Nos referimos a ciclo de vida de la persistencia como los estados de
un objeto atraviesa durante su vida.

•

Todo objeto en Hibernate tiene un contexto de persistencia.

•

Contexto de Persistencia
Es similar a una caché que recuerda todas las modificaciones y cambios de
estado realizados en los objetos de una unidad de trabajo.

•

No es visible por la aplicación y tampoco puede ser llamado.

El contexto de persistencia está definido por:
•
•

El objeto Session.en una Aplicación Hibernate
El objeto EntityManager en una Aplicación Java Persistence

© JAA JMA 2015

•

•

267

Página 117

Introducción al ciclo de vida
•

Cuando se utilizan "conversaciones" el contexto de persistencia es
crítico.
•

•

Unidades de trabajo de ejecución larga que requieren tiempo-para-pensar por parte del
usuario.

¿Cómo funciona el contexto?
 Se crea con la Aplicación Hibernate / Aplicación Java Persistent. (Session)
 Cuando una solicitud del usuario ha sido procesado, la aplicación se desconecta de la
BBDD pero el contexto de persistencia no se cierra.
 Esta desconexión dura el tiempo-para-pensar por parte del usuario.

 Al final de la conversación, el contexto de persistencia está sincronizado con la base de
datos y cerrado. (Session.close() )

© JAA JMA 2015

 Cuando el usuario continúa en la conversación, el contexto de persistencia se vuelve a
conectar a la base de datos, y la siguiente petición pueda ser procesada.

268

Introducción al ciclo de vida
•

¿Por qué utilizar un Contexto de Persistencia?
•

Hibernate puede, de forma automática, chequear los datos "sucios" y realizar una
escritura en background.
 Por ejemplo, antes de realizar una consulta SQL, con el fin de sincronizar datos correctamente.

•

El contexto puede ser utilizado como una caché de primer nivel.
 Podemos aprovechar las lectura de entidades anteriores y la ventaja de su reutilización.

•

Hibernate puede garantizar un ámbito de identidad del objeto Java.
 Dentro de un contexto, sólo existe un objeto con la misma identidad.

Hibernate puede ampliar el contexto de persistencia en cualquier momento,
añadiendo nuevas entidades o conversaciones.

© JAA JMA 2015

•

269

Página 118

Ciclo de vida. Estados
•

Hibernate define y soporta los siguientes estados de objeto:
Transient (Transitorio)
Persistent (Persistente)
Detached (Separado)
Removed (Borrado)

© JAA JMA 2015

•
•
•
•

270

Ciclo de vida. Estados
Estado Transient (Transitorio)
•

un objeto es transitorio si ha sido instanciado utilizando el operador new, y no
está asociado a una Session de Hibernate.

•

No tiene una representación persistente en la base de datos y no se le ha
asignado un valor identificador.

•

Las instancias transitorias serán destruidas por el recolector de basura si la
aplicación no mantiene más de una referencia.

•

Para convertir un objeto Transient → Persistent, utilizaremos Session.save() o
Session.saveOrUpdate()

© JAA JMA 2015

•

271

Página 119

Ciclo de vida. Estados
Estado Persistent (Persistente)
•

Una instancia persistente tiene una representación en la base de datos y un valor
identificador.

•

Los objetos se convierten en persistentes cuando se recuperan de la base de
datos, se llaman a los métodos del gestor (save, saveOrUpdate) o cuando se
crea una referencia de otro objeto persistente ya gestionado.

•

Todas las instancias Persistentes se encuentran dentro del ámbito de Session y
disponen de un identificador único (ID).

•

Hibernate detectará cualquier cambio realizado a un objeto en estado persistente
y sincronizará el estado con la base de datos cuando se complete la unidad de
trabajo.
© JAA JMA 2015

•

272

Ciclo de vida. Estados
Estado Detached (Separado)
•

Una instancia separada es un objeto que se ha hecho persistente, pero su
Session ha sido cerrada.

•

La referencia al objeto todavía es válida, y podría ser modificada en este estado

•

Una instancia separada puede ser re-unida a una nueva Session más tarde,
haciéndola persistente de nuevo (con todas las modificaciones).

•

Este aspecto habilita un modelo de programación para unidades de trabajo de
ejecución larga que requieren tiempo-para-pensar por parte del usuario.

•

Las llamamos transaccciones de aplicación, por ejemplo, una unidad de trabajo
desde el punto de vista del usuario.
© JAA JMA 2015

•

273

Página 120

Ciclo de vida. Estados
•

Estado Removed (Borrado)
•

Puede eliminar una instancia de entidad de varias maneras:
 Llamando a una operación explícita del gestor de persistencia (delete).
 De forma implícita, cuando se quitan cuando todas las referencias a la misma instancia,
el recolector de basura las elimina directamente.

© JAA JMA 2015

 Los elementos borrados son marcados para su borrado; un objeto eliminado no se debe
volver a utilizar, ya que se eliminará de la base de datos tan pronto como la unidad de
trabajo se complete.

274

Trabajo con objetos persistentes
•

En una aplicación de Hibernate, almacenar (store) y cargar (load)
objetos se realiza básicamente mediante un cambio en su estado.

•

Esto se hace en unidades de trabajo.
•

Las unidades de trabajo son "similares" a las transacciones pero no
idénticas.
Comienzo de la unidad de trabajo
Operaciones
:
Transacción1
Transacción2
:
Fin de la unidad de trabajo

© JAA JMA 2015

•

Una unidad de trabajo es un conjunto de operaciones que e ejecutan de modo
atómico.

275

Página 121

Trabajo con objetos persistentes
Unidad de Trabajo
• Una unidad de trabajo comienza con la obtención de una instancia de la sesión de
SessionFactory de la aplicación:
 SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
 Sesión session = sessionFactory.openSession ();
 Transacción tx = sesion.beginTransaction ();

• En este punto, un nuevo contexto de persistencia es creado y se encargará de
todos los objetos con los que trabaja en dicha Sesión.
• La aplicación puede tener múltiples SessionFactorys si accede a varias bases de
datos.

 La creación de una sessionFactory es muy caro
 La creación de una sessión es barato.

© JAA JMA 2015

NOTAS:

276

Trabajo con objetos persistentes
Unidad de Trabajo
• Todas las operaciones que se producen dentro de una Unidad de Trabajo están
dentro de una transacción.
• Las transacciones puede comenzar en cualquier punto de la unidad de trabajo.

© JAA JMA 2015

• Después de abrir un nuevo contexto de sesiones y persistencia, almacenaremos y
leeremos objetos.

277

Página 122

Trabajo con objetos persistentes
Creando objetos Persistentes
• Cuando creamos un nuevo objeto mediante new, el objeto es Transient.
• Para hacerlo persistente utilizamos el método session.save(objeto).
1.- Creación de elemento Transient
2.- Obtención de session y comienzo
de una transacción
3.- Llamada a save, para hacer
persistencia. Ahora se asocia a la
sesión actual y contexto de
persistencia

5.- Sesión cerrada y contexto de
persistencia cerrado.
El objeto ahora está en estado
separado.

© JAA JMA 2015

4.- Los cambios realizados en el objeto
son sincronizados con la BBDD.
También se realiza un flush() de la
memoria

278

Trabajo con objetos persistentes
Objetos Persistentes
• Debemos de tener cuidado con las transacciones.
• Si una de las sentencias implicadas en una transacción falla:
 Transacciones de BBDD
– Se deshace toda la transacción a nivel de Base de Datos

 Transacciones Hibernate
– Hibernate no deshace los cambios en la memoria a los objetos persistentes.

Memoria

© JAA JMA 2015

BBDD

279

Página 123

Trabajo con objetos persistentes
Devolviendo objetos Persistentes
• El objeto session también permite consultar la base de datos y recuperar objetos
persistentes existentes.
• Hay 2 métodos para la recuperación de objetos persistentes:
 get(objeto….)
 load(objeto….)

• En ambos métodos el elemento de objeto recuperado está en estado persistente y
cuando el contexto de persistencia se cierra, pasa a estado separado.
La única diferencia entre get() y load()
es la forma en que indican que la
instancia no se pudo encontrar

© JAA JMA 2015

GET
Devuelve NULL
LOAD
Devuelve excepción
ObjectNotFound-Exception

280

Trabajo con objetos persistentes
Modificando objetos Persistentes
• Cualquier objeto persistente devuelto por get(), load(), o cualquier entidad
consultada ya asociada con la sesión actual y contexto de persistencia se puede
modificar.
• Posteriormente deberemos sincronizarla con la con la Base de Datos. (commit)

© JAA JMA 2015

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Item item = (Item) session.get(Item.class, new Long(1234));
item.setDescription("This Playstation is as good as new!");
tx.commit();
session.close();

281

Página 124

Trabajo con objetos persistentes
Eliminación de objetos Persistentes
• Mediante el método Session.delete(objeto) podemos hacer que el estado
persistente de un objeto desaparezca.
• Después de la llamada al método delete, el trabajo con este objeto es imposible.
• La orden SQL DELETE sólo es ejecutada cuando el contexto de persistencia es
sincronizado con la Base de Datos.

© JAA JMA 2015

• Después de la sesión se cierra, el objeto se considera una instancia transitoria
ordinaria y es destruida por el recolector de basura cuando ya no está referenciada
por cualquier otro objeto

282

Trabajo con objetos persistentes
Eliminación de objetos Persistentes
¿Deberemos cargar el objeto para ser borrado? S i y no
• SI


Un objeto debería que ser cargado en el contexto de persistencia para ser borrado, es
decir, tiene que ser persistente.



¿Porque?
Todo objeto debe de estar dentro del ciclo de vida para su correcto tratamiento.
Session session = sessionFactory.openSession();
session.beginTransaction();
Profesor profesor=(Profesor) session.get(Profesor.class, 101);
session.delete(profesor);
session.getTransaction().commit();
session.close()



Podemos ejecutar SQL Nativo desde HQL o Criteria sin pasar por el ciclo de vida del
objeto
session.beginTransaction();
session.createQuery("delete from Profesor p where p.id=8").executeUpdate();
session.getTransaction().commit();

© JAA JMA 2015

• NO

283

Página 125

•

Si modificamos un objeto separado (detached), esta modificación no
persiste en la Base de Datos.

•

Tan pronto como el contexto de persistencia está cerrado, el
elemento se convierte en una instancia individual.

•

Si desea guardar las modificaciones que haya realizado en un objeto
individual, tenemos que volverlo a introducir en un contexto de
persistencia de nuevo.

•

Llamando al método update añadimos un objeto separado a una
session existente.
Session.update(objeto_separado)

© JAA JMA 2015

Trabajo con objetos Separados

284

Trabajo con objetos Separados
•

Hibernate siempre trata el objeto recién añadido como "sucio" y se
forzará la actualización del estado de persistencia del objeto en la
Base de Datos.
item.setDescription(...); // Leido en una sesion anterior

© JAA JMA 2015

Session sessionTwo = sessionFactory.openSession();
Transaction tx = sessionTwo.beginTransaction();
sessionTwo.update(item);
item.setEndDate(...);
tx.commit();
sessionTwo.close();

285

Página 126

Métodos de Sessión
•

El objeto session dispone de métodos adicionales para el control de
los objetos en el contexto de persistencia.

•

Estos métodos pueden ser utilizados de forma "manual" para
nuestra gestión.
• Session.evict( objeto )
 Se utiliza para separar, manualmente, una instancia persistente del contexto de
persistencia.

• Session.clear()

Session session = sessionFactory.openSession();
Profesor profesor =(Profesor)session.get(Profesor.class,1001);
session.evict(profesor);
session.close();

© JAA JMA 2015

 Se utiliza para separar todas las instancias persistentes del contexto de persistencia.

286

Métodos de Sessión
• Session.merge( objeto )
 ¿Qué ocurre cuando intentamos añadir un Objeto Transient a una session que ya tiene un
objeto persistente con el mismo ID?

Para solucionar este problema, utilizamos MERGE

 Si no hay objeto persistente con ese ID, intentar cargarlo o crearlo nuevo.
 Merge copia el valor de un objeto separado en un objeto persistente con el mismo ID.

© JAA JMA 2015

 Fusiona un objeto separado (detached) con otro persistente con el mismo ID.

287

Página 127

Métodos de Sessión
• Session.refresh( objeto )
 Se utiliza para recargar el estado del objeto persistente que ha sido modificado en la base
de datos por algún trigger o similar.
 Si el objeto no existe en la Base de Datos, se producirá una Excepción.
(org.hibernate.UnresolvableObjectException)
Session session = sessionFactory.openSession();
Profesor profesor = new Profesor(1001,"LLUIS", "GOMIS", "MARTINEZ");
session.refresh(profesor);
session.close();

• Session.flush()
 Los objetos no persisten en la Base de Datos hasta que se cierra la sesión

Session session = sessionFactory.openSession();
:
session.flush();
:
session.close();

© JAA JMA 2015

 Con el método flush(), forzamos la persistencia de los objetos antes de cerrar la sesión

289

Excepciones
•

Cuando Hibernate interactuar con la base de datos puede generar
SQLExceptions.

•

La gestión de excepciones en Hibernate se hace igual que en Java
básico, mediante el bloque try y catch para su control.
try {
student.setName("Johny");
student.setCourse("Hibernate");
session.merge(student);
transaction.commit();
System.out.println("Update Successfully");
session.close();
} catch (HibernateException e) {
e.printStackTrace();

•

Las excepciones mas usuales son:
 LazyInitializationException
 NonUniqueObjectException

© JAA JMA 2015

}

291

Página 128

Excepciones
LazyInitializationException
•

Esta excepción se produce cuando se intenta cargar un objeto en memoria pero la sesión ya
se ha cerrado.

•

Se suele producir cuando trabajamos con Lazy Loading ( o carga perezosa)
Session session = sessionFactory.openSession();
Profesor profesor = (Profesor) session.get(Profesor.class, 1065);
System.out.println("Leido el profesor");
System.out.println("Calle="+profesor.getDireccion().getMunicipio().getNombre());
session.close();

Todo OK

© JAA JMA 2015

Session session = sessionFactory.openSession();
Profesor profesor = (Profesor) session.get(Profesor.class, 1065);
System.out.println("Leido el profesor");
session.close();
System.out.println("Calle="+profesor.getDireccion().getMunicipio().getNombre());
org.hibernate.LazyInitializationException

292

Excepciones
NonUniqueObjectException
•

Esta excepción se produce cuando se intenta que haya más de un objeto en estado
Persistido para la misma fila de la base de datos.
Session session = sessionFactory.openSession();
session.beginTransaction();
Profesor profesor = new Profesor(1001, "LLUIS", "GOMIS", "MARTINEZ");
Profesor profesor2 = (Profesor) session.get(Profesor.class, 1001);

org.hibernate.NonUniqueObjectException

profesor.setNombre("JUAN");
session.update(profesor);
session.getTransaction().commit();
session.close();

Problema?





Hemos creado un objeto Transient con un códgo (1001) que ya existe en la BBDD
Hemos recuperado el objeto Persistente con código (1001)
Hemos modificado el objeto Transient .
Hemos intentado hacer Persistente el objeto Transient → ya existe en el contexto de Persistencia un
objeto con ese código (1001) → ERROR

© JAA JMA 2015

•

293

Página 129

© JAA JMA 2015

TRANSACCIONES Y
CONCURRENCIA

295

•

Entendemos por Transacción: un grupo de operaciones que se
ejecutan de forma atómica.

•

Las transacciones permiten a varios usuarios trabajar
simultáneamente con los mismos datos, sin comprometer la
integridad y exactitud de los datos.

•

Las transacciones son
independientes entre si

© JAA JMA 2015

Introducción

297

Página 130

Introducción
•

Las transacciones, generalmente, disponen de varios atributos:
•
•
•
•

( A ) Atomicidad
( C ) Consistencia
( I ) Aislamiento
( D ) Durabilidad

•

Atomicidad:
 En un conjunto de operaciones si una sola de ellas falla → Todas fallan.

•

Consistencia:
 Cualquier transacción llevará a la base de datos desde un estado válido a otro también válido.

•

Aislamiento:
 Es la propiedad que asegura que una operación no puede afectar a otras

Durabilidad:
 Asegura que una vez realizada la operación, ésta persistirá y no se podrá deshacer aunque falle el
sistema.

© JAA JMA 2015

•

298

Introducción
Podemos encontrar transacciones CORTAS
•

•

Una sola transacción generalmente implica un solo lote de operaciones de bases
de datos.

En la actualidad, hablamos de CONVERSACIONES
•

Un grupo atómico de las operaciones de la base de datos se producen en no uno,
sino varios lotes.

A
T
O
M
I
C
I
D
A
D

Conversación

© JAA JMA 2015

•

299

Página 131

Transacciones y BBDD
•

Bases de datos implementan el concepto de una unidad de trabajo
como una transacción de base de datos.

•

Todas las sentencias SQL se ejecutan dentro de una transacción, no
hay manera de enviar una instrucción SQL fuera de una transacción
de base de datos .

•

Una transacción de BBDD termina de una de las 2 siguientes
maneras:
Confirmada/Validada (COMMIT)
No Validada (ROLLBACK)

© JAA JMA 2015

•
•

300

Transacciones y BBDD
•

Dependiendo del SGBDR, debemos de Marcar el comienzo y Fin de
una transacción.
•
•
•

BEGIN TRANSACTION / END TRANSACTION
COMMIT ------ operaciones ------ COMMIT
Usando JDBC –
 setAutoCommit (false) – Operaciones JDBC – COMMIT/ROLLBACK

Existen SGBDR donde las transacciones son órdenes SQL
independientes (Auto-Commit).

•

Cuando tenemos programas que trabajan con Unidades de Trabajo
en varias BBDD’s necesitamos un GESTOR de TRANSACCIONES
para asegurar la atomicidad.
© JAA JMA 2015

•

301

Página 132

Transacciones e Hibernate
•

•

En el mundo de Java, existen dos mecanismos bien definidos para tratar
las transacciones en JDBC: JDBC en sí y JTA. Hibernate admite ambos
mecanismos para integrarse con transacciones y permitir que las
aplicaciones gestionen transacciones físicas.
Hibernate se puede configurar asignando valor a la propiedad
hibernate.transaction.coordinator_class:
• jdbc (el valor predeterminado para aplicaciones no JPA)
 Gestiona las transacciones a través de llamadas a java.sql.Connection, cubre solo
las transacciones sobre base de datos.

• jta

•

Si una aplicación JPA no proporciona una configuración, Hibernate
creará automáticamente el coordinador de transacciones adecuado en
función del tipo de transacción para la unidad de persistencia.

© JAA JMA 2015

 Gestiona las transacciones a través de JTA, cubre solo las transacciones sobre
múltiples recursos, incluida la base de datos.

302

Transacciones e Hibernate
•

Hibernate trabaja directamente con conexiones JDBC sin agregar
ningún comportamiento de bloqueo adicional.

•

Hibernate no bloquea objetos, por lo que las transacciones
producidas siguen el "aislamiento" definido en las bases de datos.

•

Gracias al objeto Session, Hibernate proporciona la posibilidad de
trabajar, eficientemente, con lecturas repetidas (cacheadas).

•

Para poder tener transacciones en Hibernate necesitamos:
Objeto SessionFactory
Objeto Session
© JAA JMA 2015

•
•

303

Página 133

Transacciones e Hibernate

•

Objeto SessionFactory
•

Una SessionFactory es un objeto seguro, con posibilidad de ser utilizado entre diferentes
hilos.

•

Es MUY COSTOSO, por lo que es conveniente hacerlo las mínimas veces posible.

•

Se crea una sola vez, usualmente en el inicio de la aplicación, a partir de una instancia
Configuration.

Objeto Session
•

Una Session es un objeto de BAJO COSTO.

•

Su utilización entre hilos no es segura y debe de ser usado de una sola vez ( una sola
petición, una sola conversación o una sola unidad de trabajo)

•

Las Sessions pueden ser creadas y no consumirán recursos hasta que se utilice.

© JAA JMA 2015

•

304

Transacciones e Hibernate
•

Dependiendo del tipo de transacción tendremos:
•

Transacciones CORTAS:
 Una transacción corta reduce la contención de bloqueos en la base de datos.

•

Transacciones LARGAS
 Las transacciones largas son sinónimos de una alta carga de concurrencia.
 No es recomendable mantener una transacción, de este tipo, ABIERTA durante mucho
tiempo.

•

Hay varios patrones de diseño para definir el funcionamiento
correcto de las transacciones en Hibernate:
•

sesión-por-operación (anti-patrón), sesión-por-aplicación (anti-patrón)

•

sesión-por-petición
 Es el patrón mas indicado en Hibernate

© JAA JMA 2015

 No utilizar, son pobres en Rendimiento.

305

Página 134

Transacciones e Hibernate
•

El patrón sesión-por-petición.
•

Es el patrón mas usado en Aplicaciones Multiusuario cliente/Servidor.

1. Una petición del cliente se envía al servidor (con persistencia de Hibernate).
2. Se abre una nueva Session de Hibernate y todas las operaciones de la base de
datos se ejecutan en esta unidad de trabajo.
3. Usaremos una sola transacción para servir la petición del cliente.
4. Una vez completado el trabajo y preparada la respuesta, se cierra la sesión.

© JAA JMA 2015

5. Devolución de la respuesta al Cliente.

306

Características de las Transacciones
•

En Hibernate el objeto Session utiliza un mecanismo de Lazy
Loading.
•

Hibernate no consume ningún recuro a menos que sea absolutamente necesario.

Si estamos trabajando con Pool de conexiones, la conexión JDBC
sólo se obtiene cuando comienza la transacción.

•

La llamada a beginTransaction () hace que la conexión JDBC
obtenida recientemente sea de tipo setAutoCommit (falso) .

•

A partir de este momento todas las sentencia SQL que se envíen, se
hacen en la misma transacción y conexión.
© JAA JMA 2015

•

307

Página 135

•

Después de confirmar la transacción (Commit) o deshacerla
(Rollback) , la conexión de base de datos es liberada y desvinculada
de la Sesión.

•

Nueva Transacción → Nueva Conexión del Pool.

•

Cuando la Session es liberada/cerrada, todas las instancias
persistentes son Detached (Independientes)

© JAA JMA 2015

Características de las Transacciones

308

Transacciones y Excepciones
•

Todas las excepciones producidas por Hibernate son CRITICAS.

•

Ante una excepción (incluyendo SQLException) debemos:
1. Deshacer inmediatamente la transacción de la base de datos (Rollback)
2. Descartar la instancia actual de Session. (Session.close())


Ciertos métodos Session no dejarán la sesión en un estado consistente.

3. Reiniciar otra nueva Session para seguir con el código.

Hibernate envuelve las excepciones SQLExceptions en una
subclase de JDBCException
© JAA JMA 2015

•

309

Página 136

Transacciones y TimeOut
•

Uno de los elementos básicos en las transacciones es el tiempo de
espera de la transacción.

•

Definir este tiempo de espera asegura que ninguna transacción
pueda comportarse de forma "inapropiada"
•
•

•

Que tarde mucho tiempo en ejecutarse.
Que la transacción bloquee muchos recursos durante mucho tiempo.

Hibernate define este TimeOut en el objeto Transaction.

© JAA JMA 2015

Session sess = factory.openSession();
try {
sess.getTransaction().setTimeout(3); // timeout 3 seg
sess.getTransaction().begin();
…..
sess.getTransaction().commit()
} catch (RuntimeException e) {
sess.getTransaction().rollback();
}
finally { sess.close(); }

310

Conexión

Procesar datos

• Socket
• Interrogar
servidor
• Autenticación
• Reserva e
inicialización
de recursos

• Consultas
• Transacciones

• Muy costoso

• Ligero

Cerrar
conexión
• Liberar
recursos
• Cerrar
comunicación
• Costoso
© JAA JMA 2015

Abrir conexión

311

Página 137

Conexiones
•

Problemas de las conexiones:
• Número de usuarios concurrentes
• Cierre de la conexión

•

Escenarios:
• Aplicaciones de escritorio:
 Número limitado de usuarios
 Duración determinada de la conexión
 Distribuido

• Aplicaciones web:
 Número potencialmente ilimitado de usuarios
– Si cada usuario tiene una conexión dedicada se podría saturar el servidor de base de
datos
– Es complejo saber cuando el usuario abandona el sitio (que no la página) para cerrar la
conexión

 Centralizado

© JAA JMA 2015

 Duración indeterminada de la conexión

312

Pool de Conexiones (General)
•

En general, no es aconsejable crear una conexión cada vez que
quiera interactuar con la base de datos.

•

En su lugar, las aplicaciones Java deben utilizar un pool de
conexiones.

•

Funcionamiento:
Cada sub-proceso de aplicación que tiene que trabajar con la BBDD solicita una
conexión.

2.

Esta conexión es concedida desde el POOL de Conexiones.

3.

Cuando el sub-proceso acaba (se han ejecutado todas las operaciones SQL), la
conexión es devuelta al POOL.
© JAA JMA 2015

1.

313

Página 138

Pool de Conexiones (General)
•

Hay varias razones para utilizar Pool de Conexiones:
1. El Pool de Conexiones mantiene las conexiones y reduce al mínimo el coste de
apertura y cierre de las conexiones.
2. Mediante Pool, podemos optimizar el uso de las conexiones,
activando/desconectando conexiones si hay/no hay peticiones.

© JAA JMA 2015

3. La creación de Sentencias Preparadas es caro para algunos DRIVERS,
mediante el POOL podemos cachear las sentencias entre peticiones.

314

Estrategias de configuración
•

Esquema centralizado:
• Pool de conexiones compartido entre las aplicaciones web alojadas en el
servidor JEE.
• Un único pool con una única configuración
• Un único tipo de pool de conexiones
• Configurado a nivel de servidor (requiere permisos)
• Usuario de base de datos único
• Se publica como un recurso de tipo datasource con JNDI.

Esquema distribuido:
• Pool de conexiones independientes administrados por cada aplicación web
alojadas en el servidor JEE.
• Múltiples pool con múltiples configuraciones
• Múltiples tipos de pool de conexiones, uno por aplicación
• Configurado a nivel de aplicaciones (no requiere permisos)
• Usuario de base de datos por aplicación

© JAA JMA 2015

•

315

Página 139

Pool de Conexiones con Hibernate
•

Cuando trabajamos con Hibernate, éste actúa como un cliente del
POOL de conexiones.

•

Hibernate define una arquitectura plug-in que permite la integración
con "cualquier" software de Pool de Conexiones (pero comercialmente no

•

Existe un Software libre llamado C3P0, que se integra totalmente
con Hibernate y ampliamente usado (c3p0.jar)

© JAA JMA 2015

es recomendable)

316

Pool de Conexiones con Hibernate
•

La configuración del POOL de conexiones se realiza dentro del
fichero de configuración de Hibernate (hibernate.cfg.xml).

hibernate.c3p0.min_size = 5

// Número mínimo de CX que mantiene c3p0

hibernate.c3p0.max_size = 20

// Número máximo de CX permitidas

hibernate.c3p0.timeout = 300

// Segundos de TIMEOUT para eliminar una CX

hibernate.c3p0.max_statements = 50

// Nº máximo de comandos guardados en Caché
para la utilización en Hibernate.

hibernate.c3p0.idle_test_period = 3000

// Tiempo máximo para la validación de un CX

hibernate.show_sql = true
hibernate.format_sql = true

© JAA JMA 2015

hibernate.connection.driver_class = org.hsqldb.jdbcDriver
hibernate.connection.url = jdbc:hsqldb:hsql://localhost
hibernate.connection.username = sa
hibernate.dialect = org.hibernate.dialect.HSQLDialect

317

Página 140

Pool de Conexiones con Hibernate
•

Una vez definido nuestro Pool de conexiones podríamos activar
diferentes opciones:
•

Seguimiento de las Operaciones
 hibernate.show_sql
 hibernate.format_sql
 hibernate.use_sql_comments
true
true
true

•

Estadísticas
(log4j.jar)

© JAA JMA 2015

 Apache Log4j

318




name="javax.persistence.jdbc.url“ value="jdbc:oracle:thin:@localhost:1521:xe" />
name="javax.persistence.jdbc.user" value="hr" />
name="javax.persistence.jdbc.password" value="hr" />
name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
name="hibernate.show_sql" value="true" />
name="hibernate.format_sql" value="true" />
name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
name="hibernate.c3p0.min_size" value="5" />
name="hibernate.c3p0.max_size" value="20" />
name="hibernate.c3p0.timeout" value="500" />
name="hibernate.c3p0.max_statements" value="50" />
name="hibernate.c3p0.idle_test_period" value="300"/>
name="hibernate.c3p0.preferredTestQuery" value="SELECT 1 from dual;" />
name="hibernate.c3p0.testConnectionOnCheckout" value="true" />
name="hibernate.c3p0.maxIdleTime" value="10800" />
name="hibernate.c3p0.maxIdleTimeExcessConnections" value="600"/>

© JAA JMA 2015

persistence.xml

319

Página 141

Configurar el pool de conexiones en Tomcat
El pool se configura añadiendo un fichero llamado context.xml en la
carpeta META-INF.


•

Sustituir en la sección  en persistence.xml por:
java:/com/env/jdbc/TestDB

© JAA JMA 2015

•

© JAA JMA 2015

320

321

Página 142

Introducción
•

Los Sistemas Transaccionales y BBDD tratan de asegurar el
aislamiento de transacciones.

•

Deben asegurar que durante una transacción no haya otra
transacción implicada en los mismos elementos.

•

Tradicionalmente, la concurrencia ha sido implementada con:
•
•
•

Las aplicaciones heredan el aislamiento que proporciona el sistema
de gestión de base de datos.
© JAA JMA 2015

•

Bloqueos
Regiones Críticas
Semáforos.

322

Introducción
•

Si no controlamos estos accesos, podremos encontrarnos con:
• Actualizaciones perdidas (Lost Update)
 Si dos transacciones actualizan una fila y luego la segunda
transacción se anula, causando cambios tanto que se pierdan.

• Lecturas Sucias (Dirty Reads)

© JAA JMA 2015

 Ocurre cuando una transacción lee datos modificados por otros
procesos concurrentes que aún no han realizado commit.

323

Página 143

Introducción
•

Sino controlamos estos accesos, podremos encontrarnos con:

• Análisis Contradictorios (Nonrepeatable Reads)
 Se produce si una transacción lee una fila dos veces y lee diferente
datos cada vez.

• Lecturas Fantasmas (Phantom Reads)

© JAA JMA 2015

 Se producen cuando una transacción se ejecuta una consulta en
dos ocasiones, y el segundo conjunto de resultados incluye filas que
no eran visibles en el primer conjunto de resultados

324

Niveles de Aislamiento
•

El estándar ANSI SQL define una serie de niveles de aislamiento de
transacción que coinciden con los mismos que JTA.

•

Nivel de Aislamiento:
Define el grado en que se aísla una transacción de las modificaciones de datos
realizadas por otras transacciones.

•

Este nivel de aislamiento afecta a los tipos y duración de los Bloqueos.

•

El nivel de Aislamiento cobra mayor importancia cuando mayor sea la
concurrencia.

© JAA JMA 2015

•

325

Página 144

Niveles de Aislamiento
Niveles de Aislamiento:
•

READ UNCOMMITED
 Una transacción NO puede escribir en una fila si otra transacción no confirmada ya ha escrito a la
misma.
 Cualquier transacción puede leer cualquier fila ( confirmados o no )
 Es la opción menos restrictiva, recomendable si se manejan datos de solo lectura o muy pocas
actualizaciones.

•

READ COMMITED
 Evita Lecturas Sucias, pero permite que se produzcan Análisis Contradictorios y Lecturas Fantasmas

•

REPETEABLE READ
 Sólo permite Lecturas Fantasmas.

SERIALIZABLE
 Garantiza que una transacción recuperará exactamente los mismos datos cada vez que se repita una
Select .
 Se Aplica un nivel de bloqueo que puede afectar a los demás usuarios.
 Es la opción mas restrictiva.

© JAA JMA 2015

•

326

Niveles de Aislamiento. Definición
•

Si no indicamos nada, cada conexión JDBC tiene el nivel de
aislamiento definido por el SGBD.

•

En Hibernate podemos elegir el nivel de aislamiento de las
transacciones mediante la opción:
8

1 - Read uncommitted
2 - Read committed
4 - Repeatable read
8 - Serializable

•

Hibernate configura el nivel de aislamiento en cada conexión JDBC
obtenidas del Pool de conexiones antes de iniciar una transacción.

•

Establecer el nivel de aislamiento es una opción global que afecta a
todas las conexiones y transacciones.

© JAA JMA 2015

hibernate.cfg.xml

327

Página 145

Control de Concurrencia: Bloqueos
Hay 2 técnicas de concurrencia:
•
•

Bloqueo Pesimista
Bloqueo Optimista

•

Es importante determinar qué técnica es mejor para conversaciones
largas dentro de nuestras aplicaciones.

•

Hibernate y Java Persistence utilizan el control de concurrencia
optimista, porque:
 Maximiza la eficiencia (menor aislamiento, menos bloqueos en BD)
 Es adecuada para la mayor parte de las transacciones.

© JAA JMA 2015

•

328

Control de Concurrencia: Bloqueos
Bloqueo Pesimista
•

Los datos son bloqueados previos a su modificación para evitar que nadie los
modifique.

•

Una vez que los datos a actualizar han sido bloqueados la aplicación puede
acometer los cambios, con commit o rollback, en ese caso el bloqueo es
automáticamente eliminado.

•

Si alguien intenta adquirir un bloqueo de los mismos datos durante el proceso
será obligado a esperar hasta que la primera transacción finalice.

•

Menos errores pero consume mas tiempo en su implementación.

© JAA JMA 2015

•

329

Página 146

Control de Concurrencia: Bloqueos
•

Bloqueo Pesimista
•

Los bloqueos pesimistas con obtenidos mediante el método session.lock()
sess.lock ( Elemento , LockMode.XXXXX);

Ninguna transacción simultánea puede obtener un bloqueo en los mismos datos.

Tipo de Bloqueo

Obtención

Descripción

NONE

Bajo Petición

- Representa la ausencia de un bloqueo.
- Todos los objetos se pasan a este modo de bloqueo al
final de una Transaction

UPGRADE

Bajo Petición

- Obtiene un bloqueo pesimista de UPDATE a nivel de
BBDD si es posible.
- Equivalente a un SELECT ….. FOR UPDATE

UPGRADE_NOWAIT

Bajo Petición

- Equivalente a un SELECT ….. FOR UPDATE WAIT si
se puede realizar a nivel de BBDD

WRITE

Automático

- Se adquiere automáticamente cuando Hibernate
actualiza o inserta una fila.

© JAA JMA 2015

•

330

Control de Concurrencia: Bloqueos
•

Bloqueo Pesimista
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Item i = (Item) session.get(Item.class, 123);
session.lock(i, LockMode.UPGRADE);
String description = (String)
session.createQuery("select i.description from Item i" +
" where i.id = :itemid").setParameter("itemid", i.getId() ).uniqueResult();
tx.commit();

© JAA JMA 2015

session.close();

331

Página 147

Control de Concurrencia: Bloqueos
•

Bloqueo Pesimista
•

Problemas fundamentales:
 Bloqueos:
– ¿Qué ocurre si un usuario adquiere un bloqueo y no finaliza transacción?

 Deadlock
– Bloqueos mutuos.

 En general los Sistemas RDBMS ofrecen cláusulas para este bloqueo y como tratarlo
– SELECT FOR UPDATE
– SELECT FOR UPDATE WAIT

© JAA JMA 2015

– DEADLOCK con tiempo definido y ruptura

332

Control de Concurrencia: Bloqueos
Bloqueo Optimista
•

No bloquea los registros que se van a actualizar y asume que los datos que están
siendo actualizados no van a cambiar desde que se han leído.

•

Este tipo de mecanismo, si falla, proporciona una EXCEPTION sólo al final de la
unidad de trabajo, cuando se van a guardar los datos.

•

Un bloqueo optimista siempre asume que todo va a estar bien y que las
modificaciones de datos en conflicto son raros.

© JAA JMA 2015

•

333

Página 148

Control de Concurrencia: Bloqueos
•

Bloqueo Optimista
•

Para asegura que los datos que están siendo escritos son consistentes (es decir
que ninguna otra transacción ha actualizado los datos después de la lectura), con los leídos
en primera instancia se utiliza un VERSIONADO

•

VERSIONADO:
 Se procede al leer un valor junto al registro, se actualizará ese valor a la BD cuando el
registro es actualizado.
 El chequeo de versión utiliza números de versión, o sellos de fecha (timestamps) para
detectar actualizaciones en conflicto y para prevenir la pérdida de actualizaciones

Hibernate chequea el versionado de forma automática en el momento de vaciado,
lanzando una excepción si se detecta una modificación concurrente.

•

Debemos capturar y manejar esta excepción (StaleObjectStateException )
© JAA JMA 2015

•

334

Control de Concurrencia: Bloqueos
•

Bloqueo Optimista
•

Para especificar una versión a un objeto persistente, debemos añadir un nuevo
atributo que haga de versionado (long o timestamp) y definirlo como version dentro del
archivo de mapeo de la clase.
Hibernate.cfg.xml
public class Product {
private long id;
private String name;
private long version;
:
:

Para hacerlo con anotaciones, deberemos marcar el método getVersion como
@Version
@Version
public long getVersion() {
return version;
}

Hibernate 4.X
@ Version
@ Column (name = "OBJ_VERSION")
versión int privado;

© JAA JMA 2015

•













335

Página 149

Control de Concurrencia: Bloqueos
•

Bloqueo Optimista. INCONVENIENTES
•

Si deseamos que el versionado sea automática, deberemos modificar la Tabla
correspondiente para añadirle una nueva columna para la versión.

Hibernate propone la siguiente solución
• Utilizar todos los campos del objeto persistente para comprobar que nada en
una fila se ha modificado antes de actualizar una fila.

• Deberemos añadir lo siguiente en el fichero Tabla.hbm.xml correspondiente


© JAA JMA 2015

• Sólo es válido dentro del mismo Contexto de Persistencia (Session)

336

© JAA JMA 2015

CACHE

337

Página 150

Tipos de caché en Hibernate
•
•

El uso de técnicas de caché puede reducir el número de consultas que
se lanzan contra la BD
Caché de primer nivel
• Dentro de una transacción, Hibernate cachea los objetos que se recuperan
de BD en la sesión (objeto Session)
 Nunca se recupera más de una vez un mismo objeto
 Sólo se cachean mientras dura la transacción

• Este tipo de caché es implícita al modelo de Hibernate

•

Caché de segundo nivel
• Permite cachear el estado de objetos persistentes a nivel de proceso
• Este tipo de caché es opcional y requiere configuración

Caché de resultados de búsqueda
• Permite cachear resultados de una búsqueda particular
• Este tipo de caché está integrada con la caché de segundo nivel

© JAA JMA 2015

•

338

Cache de Primer Nivel
•

•

•

© JAA JMA 2015

•

Es el que mantiene automáticamente Hibernate cuando dentro de una
transacción interactuamos con la base de datos, en éste caso se
mantienen en memoria los objetos que fueron cargados y si mas
adelante en el flujo del proceso volvemos a necesitarlos van a ser
retornados desde el cache, ahorrando accesos sobre la base de datos.
Lo podemos considerar como un cache de corta duración ya que es
válido solamente entre el begin y el commit de una transacción, en forma
aislada a las demás.
Hibernate lo maneja por defecto, no hay que configurar nada, están
vinculadas a las Session o EntityManager.
Para deshabilitar o evitar el uso del cache, hay que utilizar una
StatelessSession, no crea la cache de Primer Nivel, es casi como si se
utilizara JDBC directamente.

339

Página 151

•
•

•

•

•

Una sesión (Session) de Hibernate, es un caché de datos persistentes a
nivel de la transacción.
Es posible configurar un caché a nivel de cluster o a nivel de la JVM (a
nivel de la SessionFactory), denominada caché de Segundo Nivel, sobre
una base de clase-por-clase o colección-por-colección.
Hay que tener en cuenta que los cachés nunca están al tanto de los
cambios que otra aplicación haya realizado al almacén persistente (se
pueden configurar para que los datos en caché expiren regularmente).
Existe la opción de decirle a Hibernate qué implementación de cacheo
usar, especificando el nombre de una clase que implemente
org.hibernate.cache.CacheProvider, usando la propiedad
hibernate.cache.provider_class.
Hibernate trae incorporada una buena cantidad de integraciones con
proveedores de cachés open-source. Además, se puede implementar un
caché propio y enchufarlo.

© JAA JMA 2015

Caché de Segundo Nivel

340

Estrategias de almacenamiento en caché
•

read-only:
• Si su aplicación necesita leer pero nunca modificar las instancias de una
clase persistente, se puede usar un caché read-only. Esta es la estrategia
más simple y la de mejor rendimiento. También es perfectamente segura de
utilizar en un cluster.

read-write:
• Si la aplicación necesita actualizar datos, puede ser apropiado usar una
caché de lectura-escritura (read-write). Esta estrategia de cacheo nunca
debería ser usada si se requiere aislamiento de transacciones serializables.
• Si el caché se usa en un entorno JTA, se debe especificar la propiedad
hibernate.transaction.manager_lookup_class, especificando una estrategia
para obtener la propiedad TransactionManager de JTA.
• En otros entornos, hay que asegurarse de que la transacción esté completa
para cuando ocurran Session.close() o Session.disconnect().
• Si se quiere usar esta estrategia en un cluster, hay que asegurarse de que la
implementación subyacente de caché soporta "locking". Los proveedores de
caché que vienen ya incorporados no lo soportan.

© JAA JMA 2015

•

341

Página 152

Estrategias de almacenamiento en caché
•

nonstrict-read-write:
• Si la aplicación necesita actualizar datos, pero sólo ocasionalmente (es decir,
si es improbable que dos transacciones traten de actualizar el mismo ítem
simultáneamente), y no se requiere un aislamiento de transacciones estricto,
puede ser apropiado un caché "de lecto-escritura no estricta" (nonstrict-readwrite).
• Si el caché se usa en un entorno JTA, se debe especificar
hibernate.transaction.manager_lookup_class.
• En otros entornos, hay que asegurarse de que la transacción esté completa
para cuando ocurran Session.close() o Session.disconnect().

transactional:
• La estrategia transaccional (transactional) provee soporte para proveedores
de caché enteramente transaccionales, como JBoss TreeCache. Tales
cachés sólo pueden ser usados en un entorno JTA, y se debe especificar
hibernate.transaction.manager_lookup_class.

© JAA JMA 2015

•

342

Administrar los cachés
•

Acciones que agregan un elemento al caché interno de la sesión.
• Guardar o actualizar un artículo: save(), update(), saveOrUpdate())
• Recuperando un artículo: load(), get(), list(), iterate(), scroll()

•

•

© JAA JMA 2015

•

El estado de un objeto se sincroniza con la base de datos cuando llama
al método flush(). Para evitar esta sincronización, puede eliminar el
objeto y todas las colecciones de la caché de primer nivel con el método
evict() o eliminar todos los elementos de la caché de sesión con el
método clear().
La sesión proporciona un método contains() para determinar si una
instancia pertenece a la caché de la sesión.
Para el caché de segundo nivel, hay métodos definidos en Factory para
expulsar el estado en caché de una instancia, todas las instancias de una
clase, una colección de una instancia o todas las instancias de una clase.

343

Página 153

CacheMode
El CacheMode controla la manera en que interactúa una sesión en particular con el
caché de segundo nivel:
•

CacheMode.NORMAL:
 JPA: CacheStoreMode.USE, CacheRetrieveMode.USE
 lee ítems desde y escribe ítems hacia el caché del segundo nivel

•

CacheMode.GET:
 JPA: CacheStoreMode.BYPASS, CacheRetrieveMode.USE
 lee ítems del caché del segundo nivel. No escribe al caché de segundo nivel excepto cuando
actualiza datos

•

CacheMode.PUT:
 JPA: CacheStoreMode.USE, CacheRetrieveMode.BYPASS
 escribe ítems al caché de segundo nivel. No lee del caché de segundo nivel

•

CacheMode.REFRESH:

•

CacheMode.IGNORE
 JPA: CacheStoreMode.BYPASS, CacheRetrieveMode.BYPASS
 No lee ítems desde y ni escribe ítems hacia el caché del segundo nivel

© JAA JMA 2015

 JPA: CacheStoreMode.REFRESH, CacheRetrieveMode.BYPASS:
 escribe ítems al caché de segundo nivel. No lee del caché de segundo nivel, saltándose el
efecto de hibernate.cache.use_minimal_puts, forzando la actualización del caché de segundo
nivel para todos los ítems leídos de la base de datos

344

Regiones
•

Un principio básico es dividir la caché en diversas "regiones" donde se
ubican los objetos. Estas regiones son configurables de forma
independiente.

•

Hibernate necesita regiones de caché para 4 usos distintos:
• datos de entidades: representación de los datos de las entidades
• datos de colecciones: referencia a las entidades de las colecciones
• resultados de consultas:

© JAA JMA 2015

 StandardQueryCache: representación de los resultados de consultas,
 UpdateTimestampsCache: marcas timestamps para el control de versiones de los
datos almacenados en StandardQueryCache para ser poder "invalidarlos" cada
vez que se modifiquen los datos subyacentes. (no debe caducar)

345

Página 154

•
•
•

•
•

•
•

hibernate.cache.region.factory_class: Establece el proveedor a utilizar.
hibernate.cache.use_second_level_cache: Habilitar el almacenamiento
en caché de segundo nivel en general.
hibernate.cache.use_query_cache: Habilitar el almacenamiento en caché
de segundo nivel de los resultados de la consulta. El valor
predeterminado es falso.
hibernate.cache.query_cache_factory: Implementación encargada de la
invalidación de los resultados de consultas.
hibernate.cache.use_minimal_puts: Optimiza las operaciones de caché
de segundo nivel para minimizar las escrituras, a costa de lecturas más
frecuentes.
hibernate.cache.region_prefix: Nombre que se utilizará como prefijo para
todos los nombres de región de caché de segundo nivel.
hibernate.cache.default_cache_concurrency_strategy: read-only, readwrite, nonstrict-read-write, transactional.

© JAA JMA 2015

Configuración de caché

346

Configuración de caché
•

javax.persistence.sharedCache.mode: Modo de cacheo de las entidades.
Los siguientes valores son posibles:
• ENABLE_SELECTIVE (Valor por defecto y recomendado):
 Las entidades no se almacenan en caché a menos que se marquen explícitamente
como almacenables (con la anotación @Cacheable).

• DISABLE_SELECTIVE:
 Las entidades se almacenan en caché a menos que se marque explícitamente
como no almacenable en caché.

• ALL:
 Las entidades siempre se almacenan en caché incluso si están marcadas como no
almacenables en caché.
 Ninguna entidad se almacena en caché, incluso si se marca como almacenable en
caché. Esta opción básicamente desactiva el almacenamiento en caché de
segundo nivel.

© JAA JMA 2015

• NONE:

347

Página 155

Cache de entidades
Para indicar que una entidad se debe cachear se utiliza la anotación
@Cacheable (@Cacheable(false) no se debe cachear) y se configura con la
anotación @Cache:
•
•

•

usage: estrategia de concurrencia de caché dada, que puede ser: NONE,
READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL.
region: La región de caché. Este atributo es opcional y toma como valor
predeterminado el nombre de clase completamente calificado de la clase, o el nombre
de rol calificado de la colección.
include: all incluye todas las propiedades (predeterminado) o non-lazy solo incluye
propiedades no perezosas.
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public static class Profesor {
@OneToMany(mappedBy = “profesor", cascade = CascadeType.ALL)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private List phones = new ArrayList<>( );

© JAA JMA 2015

•

348

Caché de Consultas
•

•

•

Los conjuntos de resultados de peticiones también pueden ponerse en
caché. Esto solamente es útil para consultas que se ejecutan
frecuentemente con los mismos parámetros.
El poner en caché los resultados de una petición introduce algunos
sobrecostos en términos del procesamiento transaccional normal de sus
aplicaciones.
Para utilizar el caché de peticiones primero necesita habilitar el caché de
peticiones:
• hibernate.cache.use_query_cache true

Esta configuración crea dos nuevas regiones de caché:
• org.hibernate.cache.StandardQueryCache, mantiene los resultados de la
petición en caché
• org.hibernate.cache.UpdateTimestampsCache, mantiene los sellos de fecha
de las actualizaciones más recientes a las tablas de peticiones. Estas se
utilizan para validar los resultados ya que se sirven desde el caché de
peticiones.

© JAA JMA 2015

•

349

Página 156

Caché de Consultas
•

Para cachear el resultado de una consulta:
List persons = entityManager.createQuery(
"from Person p " +
"where p.name = :name", Person.class)
.setParameter( "name", "John Doe")
.setHint( "org.hibernate.cacheable", "true")
.getResultList();

Para cachearlo en una región especifica:
List persons = entityManager.createQuery(
"from Person p " +
"where p.id > :id", Person.class)
.setParameter( "id", 0L)
.setHint( QueryHints.HINT_CACHEABLE, "true")
.setHint( QueryHints.HINT_CACHE_REGION, "query.cache.person" )
.getResultList();

© JAA JMA 2015

•

350

Hints de Cache
QueryHints.HINT_CACHEABLE:
•

•

QueryHints.HINT_CACHE_MODE:
•

•

especificar el nombre de la región de caché (dentro de la región de caché de resultados
de la consulta de Hibernate).

"javax.persistence.cache.retrieveMode”
•

•

especificar el modo de caché (CacheMode) que está en efecto para la ejecución de la
consulta insinuada: CacheMode.NORMAL, CacheMode.GET, CacheMode.PUT,
CacheMode.REFRESH, CacheMode.IGNORE

QueryHints.HINT_CACHE_REGION:
•

•

especificar si los resultados de la consulta se deben almacenar en caché.

especificar si se usa u omite la cache cuando los datos y las consultas recuperan:
CacheRetrieveMode.USE, CacheRetrieveMode.BYPASS

"javax.persistence.cache.storeMode”
•

especificar cuando se confirman los datos de la cache:
 BYPASS: No insertar en el caché.
 REFRESH: Insertar/actualizar los datos de la entidad en la memoria caché cuando se lee de la
base de datos y cuando se confirma en la base de datos.
 USE: Insertar los datos de la entidad en la memoria caché cuando se lea de la base de datos e
inserte/actualice los datos de la entidad cuando se confirma en la base de datos: este es el
comportamiento predeterminado.

© JAA JMA 2015

•

351

Página 157

•
•
•
•
•

•

•

•

name: Nombre de la caché. Ha de ser único.
maxElementsInMemory: Número máximo de objetos que se crearán en memoria.
eternal: Marca que los elementos nunca expirarán de la caché. Serán eternos y
nunca se actualizarán. Ideal para datos inmutables.
overflowToDisk: Marca que los objetos se guarden en disco si se supera el límite
de memoria establecido.
timeToIdleSeconds: Es el tiempo de inactividad permisible para los objetos de
una clase. Si un objeto sobrepasa ese tiempo sin volver a activarse, se expulsará
de la caché.
timeToLiveSeconds: Marca el tiempo de vida de un objeto. En el momento en que
se sobrepase ese tiempo, el objeto se eliminará de la caché, independientemente
de cuando se haya usado.
diskPersistent: Establece si los objetos se almacenarán a disco. Esto permite
mantener el estado de la caché de segundo nivel cuando se apaga la JVM, es
decir cuando se cae la máquina o se para el servidor o la aplicación.
diskExpiryThreadIntervalSeconds: Es el número de segundos tras el que se
ejecuta la tarea de comprobación de si los elementos almacenados en disco han
expirado.

© JAA JMA 2015

Configuración propia del proveedor

352

VALORACIÓN DE LA ACCIÓN
FORMATIVA
Tu opinión es muy importante para nosotros, por eso solicitamos tu colaboración para
analizar la calidad de esta acción formativa y para identificar elementos de mejora .

www.iconotc.com

© JAA JMA 2015

ACCEDE AL CUESTIONARIO

353

Página 158

www.iconotc.com

© JAA JMA 2015

¡Seguimos en contacto!

354

Página 159


Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 159
Language                        : es-ES
Tagged PDF                      : Yes
XMP Toolkit                     : 3.1-701
Producer                        : Microsoft® PowerPoint® 2019
Title                           : ervlets y JSP
Creator                         : JAA
Creator Tool                    : Microsoft® PowerPoint® 2019
Create Date                     : 2019:02:10 19:39:44+01:00
Modify Date                     : 2019:02:10 19:39:44+01:00
Document ID                     : uuid:F6F392DF-02DE-49B2-A780-D8025CA24BEE
Instance ID                     : uuid:F6F392DF-02DE-49B2-A780-D8025CA24BEE
Author                          : JAA
EXIF Metadata provided by EXIF.tools

Navigation menu