m3-uf2 persistencia con hibernate


eugeniaperez.es

Unidad 1: Arquitectura del ORM

m3-uf2 persistencia con hibernate

 

eugeniaperez.es

Unidad 1: Arquitectura del ORM

  • Es un framework ORM
  • Elimina código boilerplate
  • Aplicado junto con el patrón DAO
  • Diseño desacoplado, sencillo y mantenible
  • Abstracción del origen de datos
  • Mejora la productividad
  •  Permite reemplazar fácilmente el SGBD 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.1 Arquitectura de gestión

 

El patrón DAO es un patrón de diseño que permite separar la lógica de negocio con los detalles de acceso a datos

Implementa operaciones CRUD necesarias y adicionales

La información entre el DAO y la aplicación se realiza mediante objetos (tablas de la BD)

1.1.1 EL PATRÓN DAO

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.1 Arquitectura de gestión

 

Ejemplo práctico: BD ERP, con una tabla Customer

  • Customer: representa los datos de la tabla. Intercambiarinformación entre el programa y la clase DAO.
  • CustomerDAO: se encarga de todas las operaciones CRUD.
  • DataSource: se encarga de conseguir la conexión con el origen de datos.

1.1.1 EL PATRÓN DAO

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.1 Arquitectura de gestión

 

Ejemplo práctico: BD ERP, con una tabla Customer

  • Customer: datos tabla
  • CustomerDAO:  CRUD
  • DataSource: conexión 

1.1.1 EL PATRÓN DAO

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.1 Arquitectura de gestión

 

1.1.1 EL PATRÓN DAO

HIBERNATE 

Interactúa directamente con un SGBDR y SQL

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

A través de Maven:

El diagrama en concreto a representar es:

 

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Elementos necesarios:

  • Incluye las dependencias (org.hibernate y mysql-connector) en el pom.xml
  • Crea un archivo hibernate.cfg.xml en src
  • Crea un fichero customer.hbm.xml que mapee dicha entidad así como el POJO correpondiente

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

hibernate.cfg.xml : fichero de configuración de hbm

 

 

<?xml version='1.0' encoding='utf-8'?>
<!-- Hibernate configuration file, here is were we set up hibernate db collection 
	and mapping between classes and database tables. -->
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <!-- contenido -->
</hibernate-configuration>

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

hibernate.cfg.xml : fichero de configuración de hbm

 

 

<session-factory>
    <!-- Database connection settings -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/testdb</property>
    <property name="connection.username">test</property>
    <property name="connection.password">test</property>

    <property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
    <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory
    </property>
    <property name="current_session_context_class">thread</property>
    <property name="hibernate.show_sql">false</property>
    <property name="hbm2ddl.auto">create</property>
</session-factory>

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

hibernate.cfg.xml : fichero de configuración de hbm

 

Propiedad hbm2ddl.auto:

  • Validate = Valida el esquema de la BD
  • Update = Solo actualiza la BD
  • Create = Borra el esquema existente y crea uno nuevo.
  • Create-drop = Crea una nueva base de datos y la elimina cuando la SessionFactory es destruida. 

 

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

hibernate.cfg.xml : fichero de configuración de hbm

 

Existe otra propiedad pool_size:

 

 

Por defecto tiene valor 1.  Cuanto mayor sea el valor menos posibilidad de peticiones pendientes en cola, pero también será más lenta...

 

 

<property name="connection.pool_size">10</property>

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

hibernate.cfg.xml : fichero de configuración de hbm

 

 

<session-factory>
    ...
    <!-- Database connection settings -->
    <mapping resource="Customer.hbm.xml" />
    
</session-factory>

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Customer.hbm.xml : fichero de configuración de hbm

 

 

<hibernate-mapping package="org.sistema.test.Test">

	<class name="Customer" table="CUSTOMERS">
		<id name="id" column="ID">
			<generator class="identity" />
		</id>
		<property name="name" column="NAME" />
		<property name="address" column="ADDRESS" />
		<property name="email" column="EMAIL" />
	</class>

</hibernate-mapping>

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Estrategias de generación de id:

  • Si necesitamos un id autogenerado: class=identity
  • Si especificamo class=native estaremos permitiendo que sea Hibernate quién seleccione la estrategia adecuada al SGBD, esto es, identity para MySQL, sequence para Oracle, etc.
  • class = assigned permite que la propia aplicación sea quien le de el valor al Id.

 

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

1.1 Java Persistence API

 

Java Persistence API (JPA) es la API de persistencia desarrollada para la plataforma Java EE. Es un framework que maneja datos relacionales en aplicaciones usando la Plataforma Java en sus ediciones Java SE y Java EE.

Conserva las ventajas de la OO al seguir el patrón de mapeo objeto-relacional y permitir usar  POJOs.

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Se crea la clase Java Customer que representa a la tabla (POJO):

  • Siempre un contructor por defecto.
  • Por cada propiedad deberemos tener un get/set asociado. 
  • De forma opcional, implementar la interfaz Serializable.
  • El Identificador será preferiblemente de tipos nullables (Integer, Long, etc.) mejor que de tipos básicos (int, long, etc.). 

 

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Text

public class Customer {
	private Long id;
	private String name;
	private String address;
	private String email;

	/**
	 * Default constructor
	 */
	public Customer() {
	}

        /**
        * GETTERS AND SETTERS
        */
        ...
}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

  • Crea la interfaz del DAO y su implementación con las operaciones CRUD que se van a probar
  • Finalmente, instancia el DAO desde un programa principal y pruébalo...

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Interfaz DAO:

 

public interface CustomerDAO {

	public Customer selectById(Long id);

	public List<Customer> selectAll();

	public void insert(Customer customer);

	public void update(Customer customer);

	public void delete(Customer customer);

}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Implementación DAO:

 

public class HibernateCustomerDAO implements CustomerDAO {

	public Customer selectById(Long id) {
		SessionFactory sessionFactory = HibernateSession.getSessionFactory();
		Session session = sessionFactory.openSession();
		Customer customer = (Customer) session.get(Customer.class, id);
		session.close();
		return customer;
	}


	public List<Customer> selectAll() {
		SessionFactory sessionFactory = HibernateSession.getSessionFactory();
		Session session = sessionFactory.openSession();
		List<Customer> customers = session.createCriteria(Customer.class).list();
		session.close();
		return customers;
	}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Text

        public void insert(Customer customer) {
		SessionFactory sessionFactory = HibernateSession.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		Long id = (Long) session.save(customer);
		customer.setId(id);
		session.getTransaction().commit();
		session.close();
	}


	public void update(Customer customer) {
		SessionFactory sessionFactory = HibernateSession.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.merge(customer);
		session.getTransaction().commit();
		session.close();
	}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

La sesión de Hibernate

Hbm carga el fichero de config para crear una SessionFactory o factoría global de objetos Session

La Sesión nos permitirá realizar todo tipo de operaciones contra BD (inserción, borrado, cargado de registros, etc) manteniendo un medio transaccional.

Se define un SessionFactory por cada una y solo una de las BD

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

La sesión de Hibernate

La principal función de esta interfaz es ofrecer operaciones de creación, lectura y borrado de entidades de nuestro modelo. 

Una entidad puede estar en estos 3 estados:

  • transient: nunca ha sido persistida...
  • persistent: asociado con una Session.
  • detached: ha sido persistente, pero ya NO está asociada con el objeto Session

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

La sesión de Hibernate

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

  • save(): persiste una transient a través de  INSERT SQL.
  • persist():se diferencia de save() en que la inserción no se produce inmediatamente, si no cuando se realiza un flush...
  • saveOrUpdate(): salva o actualiza una entidad.
  • delete(): borra una entidad de la base de datos.
  • get(): recupera una entidad da partir de su ID.
  • load(): recupera un proxy que contiene el ID de la entidad.
  • update():  actualizando los cambios producidos
  • merge(): igual que el anterior pero también fuera de la Sessión.

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Por último la clase HibernateSession:

 

public class HibernateSession {
	private static final SessionFactory sessionFactory = buildSessionFactory();
	private static Session session;

	private static SessionFactory buildSessionFactory() {
		Configuration configuration = new Configuration();
		configuration.configure("hibernate.cfg.xml");
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
				.applySettings(configuration.getProperties())
				.buildServiceRegistry();
		SessionFactory sessionFactory = configuration
				.buildSessionFactory(serviceRegistry);
		return sessionFactory;
	}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Por último la clase HibernateSession:

 

public class HibernateSession {
        ...
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	
	public static Session getSession() {
		if (null == session) {
			session = sessionFactory.openSession();
		}
		return session;
	}
}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Descarga el proyecto maven_test del repositorio de Bitbucket:

Usuario: 

Psswd:

URL: https://eugenia_perez@bitbucket.org/eugenia_perez/maven_test.git

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Configuración basada en anotaciones:

El infierno XML:

  • demasiado largo de escribir
  • muy repetitivo ,
  • susceptible y fuente de numerosos errores, etc.

Se crea una alternativa:  anotaciones Java en el propio código

  • Forma más compacta y sencilla

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Configuración basada en anotaciones:

En el fichero hibernate.cfg.xml especificaremos un POJO, en lugar del fichero de mapeo.

 

 


    <!-- Here comes the concrete path to refer our AJO file -->
    <mapping class="org.sistema.test.TestAnnotations.Customer" />

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Y anotamos nuestro POJO o AJO (Annotated Java Object). 

 

 

@Entity
@Table(name="CUSTOMERS")
public class Customer {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="CUSTOMER_ID")
	private Long id;
	@Column(name="CUSTOMER_NAME")
	private String name;
	private String address;
	private String email;

        /**
        * Default constructor
        * Getters and setters
        */
}

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Estrictamente las anotaciones obligatorias que deberíamos incluir son (anotaciones estándar JPA -> javax.persistence):

  • @Entity: Se aplica a la clase e indica que esta clase Java es una entidad a persistir. 
  • @Id: Se aplica a una propiedad Java e indica que este atributo es la clave primaria. 

 

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

De manera opcional:

  • @Table(name=”CUSTOMERS”) 
  • @Column(name=“ID”):
  • @GeneratedValue: crea un id según estrategia. Strategy: mediante GenerationType, de valores:
    • IDENTITY: en MySQL -> AUTO_INCREMENT.
    • AUTO: equivalente a NATIVE

 

 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Descarga el proyecto maven_test_annotations del repositorio de Bitbucket:

Usuario: 

Psswd:

URL: https://eugenia_perez@bitbucket.org/eugenia_perez/maven_test.git



m3-uf2 persistencia con hibernate

 

eugeniaperez.es

FIN DE LA UNIDAD 1: Arquitectura del ORM

m3-uf2 persistencia con hibernate


eugeniaperez.es

Unidad 2: JPA VS. HIBERNATE

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.1 Java Persistence API

 

Java Persistence API (JPA) es la API de persistencia (javax.persistence) desarrollada para la plataforma Java EE. Es un framework que maneja datos relacionales en aplicaciones usando la Plataforma Java en sus ediciones Java SE y Java EE.

Conserva las ventajas de la OO al seguir el patrón de mapeo objeto-relacional y permitir usar  POJOs.

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.1 Java Persistence API

 

  • JPA combina ideas y conceptos de los principales frameworks de persistencia, como Hibernate.
  • El mapeo objeto-relacional se realiza mediante anotaciones
  • Se utiliza un motor de persistencia para la traducción entre objetos-registros
  • Para su configuración se utiliza persistence.xml ( hibernate.cfg.xml)

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.2 Implementaciones de JPA

 

Existen muchas entre las cuáles Hibernate es la más usada. Destacan las siguientes:

JPA establece una interface común que es implementada por un proveedor de persistencia  (Hibernate) que podemos elegir

El proveedor quién realiza el trabajo funcionando bajo la API de JPA.

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Si en un proyecto queremos utilizar la API JPA pero con Hibernate como ORM subyacente utilizaremos la dependencia:

  •  org.hibernate cuyo artifactId sea hibernate-entitymanager

Crearemos una entidad simple o POJO (@Entity):

  • Con constructor por defecto 
  • Que sea clase de primer nivel (no interna)
  • No sea final
  • Implementar la interface java.io.Serializable 

 

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Todas las entidades poseen una identidad que las diferencia del resto: @Id  (Mejor Integer que int) Lo recomendable es Long

Para hacerla autogenerada: @GeneratedValue

Por defecto: las entidades serán mapeadas a una tabla de la BD del mismo nombre, y cada una de sus propiedades será mapeada a una columna con el mismo nombre también.

  • Es posible variar esto con @Table y @Column

 

 

 

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Por defecto las propiedades se leen tempranamente:

 

Pero es un comportamiento que se puede variar con la lectura demorada, para evitar el coste de crear la entidad si no se utiliza:

 

 

@Basic(fetch = FetchType.EAGER)
private Image banner;
@Basic(fetch = FetchType.LAZY)
private Image banner;

Se debe utilizar con moderación puesto que compromete el rendimiento

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

JPA puede mapear los tipos enumerados (enum) mediante la anotación @Enumerated:

 

Por defecto de JPA mapeará cada valor ordinal a una columna de tipo numérico en la base de datos: 

  • Genre.COMEDY  insertará el valor 2

Se puede variar para almacenar su nombre:

 

 

@Enumerated
private Genre genre;

...

public enum Genre { 
    HORROR, 
    DRAMA, 
    COMEDY, 
    ACTION
} 
@Enumerated(EnumType.STRING)
private Genero genero;

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Ciertas propiedades deberían actualizarse en función de un estado: @Transient. Por ejemplo, la edad de una Persona.

Su valor puede ser calculado en tiempo de ejecución gracias a la propiedad fechaNacimiento.

 

 

@Transient
private int age;
public int getAge() { 
    // workout the age and return it 
}
@Entity 
public class Person { 
    @Id 
    @GeneratedValue 
    private Long id; 
    private String name; 
    private String surname; 
    private Date dateOfBirth; 
    private int age; 
     
    // getters y setters 
} 

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Los tipos insertables (embeddable types) son objetos que no tienen identidad, por lo que para ser persistidos deben ser primero insertados dentro de una entidad.

Se declaran con @Embeddable:

 

 

 

 

 

@Embeddable 
public class Address { 
    private String streetName; 
    private int postalCode; 
    
    // ... 
} 
@Entity 
public class Person { 
    // ... 
    
    @Embedded 
    private Address address; 
} 

Se insertan con @Embbeded:

unidad 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

 

Es necesario ser coherente con el tipo de acceso:

  • Acceso a variable (field access)
  • Acceso a propiedad (property access)

El tipo de acceso que usará una entidad está definido por el lugar donde situemos sus anotaciones de mapeo.

Es necesario ser congruente, evitando mezclar los tipos. 

 

 

 

 

 

 

unidad 2: JPA VS. HIBERNATE

 

2.3 Hibernate: implementación de JPA

 

@Embeddable 
public class Insertable { 
    private int variable; 

@Column(name = "VALOR_DOBLE") 
    public int getVariable() { 
        return variable * 2; 
    } 
     
    public void setVariable(int variable) { 
        this.variable = variable; 
    } 
} 

@Entity 
public class Entity 
    @Id 
    @GeneratedValue 
    private Long id; 
    @Embedded 
    private Insertable insertable; 
} 

UNIDAD 2: JPA VS. HIBERNATE

 

eugeniaperez.es

2.3 Hibernate: implementación de JPA

Para evitar dichos problemas utilizaremos la anotación @Access

  • Bien indicando acceso por propiedad:  AccessType.PROPERTY
  • O bien indicando acceso por variable:  AccessType.FIELD
@Embeddable
@Access(AccessType.PROPERTY)
public class Insertable { ... }
@Embeddable
@Access(AccessType.FIELD)
public class Insertable { ... }

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.1 Archivos de configuración 

La configuración de Hibernate puede hacerse en tres lugares:

  • Un archivo de propiedades llamado "hibernate.properties"
  • Un archivo XML llamado "hibernate.cfg.xml"
  • En código dentro de la misma aplicación

Los archivos pueden tener cualquier nombre, pero Hibernate buscará por defecto los archivos con los nombres que he mencionado, en una ubicación predeterminada 

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Descarga el proyecto jpaExample del repositorio de Bitbucket:

Usuario: 

Psswd:

URL: https://eugenia_perez@bitbucket.org/eugenia_perez/jpaexample.git

 

 

m3-uf2 persistencia con hibernate


eugeniaperez.es

FIN DE LA UNIDAD 2: JPA VS. HIBERNATE

m3-uf2 persistencia con hibernate


eugeniaperez.es

Unidad 3: Configuración de hibernate

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.1 Archivos de configuración 

La configuración de Hibernate puede hacerse en tres lugares:

  • Un archivo de propiedades llamado "hibernate.properties"
  • Un archivo XML llamado "hibernate.cfg.xml"
  • En código dentro de la misma aplicación

Los archivos pueden tener cualquier nombre, pero Hibernate buscará por defecto los archivos con los nombres que he mencionado, en una ubicación predeterminada 

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.2 El archivo hibernate.cfg.xml

El contenido mínimo:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
</hibernate-configuration>

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.2 El archivo hibernate.cfg.xml

  • Configuraremos un session-factory y los parámetros de conexión:
<hibernate-configuration>
<session-factory>
		<!-- Database connection settings -->
		<property
		name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<property 
		name="connection.driver_class">com.mysql.jdbc.Driver</property>
		<property 
		name="connection.url">jdbc:mysql://localhost:3306/test</property>
		<property name="connection.username">test</property>
		<property name="connection.password">test</property>

		<property name="hibernate.show_sql">true</property>
		<property name="hbm2ddl.auto">create-drop</property>
</session-factory>
</hibernate-configuration>

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.2 El archivo hibernate.cfg.xml

  • El valor de hbm2ddl.auto  depende de la operación:
    • validate: valida el schema, no hace cambios en la BD.
    • update: actualiza el schema.
    • create: crea el schema, destruyendo la información anterior.
    • create-drop: elimina el schema al final de la sesión.

UNIDAD 3: CONFIGURACIÓN DE HIBERNATE

 

eugeniaperez.es

3.2 El archivo hibernate.cfg.xml

  • Finalmente por cada fichero de mapeo se incluirá una línea con el elemento <mapping>:
<mapping resource="mappings/Customer.hbm.xml"/>

Una vez que construyas el fichero cfg.xml lo ubicarás en la carpeta resources.

m3-uf2 persistencia con hibernate

 

eugeniaperez.es

FIN DE UNIDAD 3: Configuración de Hibernate

m3-uf2 persistencia con hibernate


eugeniaperez.es

Unidad 4: Mapeo de clases persistentes

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.1 Asociaciones

En Hibernate existen 4 tipos de relaciones:

  • Uno a Uno
  • Uno a Muchos
  • Muchos a Uno
  • Muchos a Muchos

Cada una de éstas podrá ser unidireccional o bidireccional.

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Una ocurrencia solo puede relacionarse con una entidad

 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Mediante archivos de mapeo XML (address.hbm.xml)

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.sistema.hibernate.oneToOne">

	<class name="Address" table="address">
		<id name="id" column="id">
			<generator class="identity" />
		</id>
		<property name="street" column="street" />
		<property name="postCode" column="postCode" />
	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

En el mapeo de Persona queremos reciba el mismo identificador que la Direccion, mediante el generador foreign:

 

 

<hibernate-mapping package="org.sistema.hibernate.oneToOne.models">
	<class name="Person" table="person">
		<id name="id" column="id">
			<generator class="foreign">
				<param name="property">address</param>
			</generator>
		</id>
		<property name="name" />
	</class>
</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Ahora agregaremos la siguiente línea para indicar a través del name cómo se llama el atributo en la clase Persona que indica la relación 1:1 con dirección.

 

​Mediante el atributo cascade podremos indicarle distintas operaciones que se realizarán en los hijos a la vez que en los padres:

 

<one-to-one name="address" cascade="persist, delete" />

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

La mayoría de los valores corresponde con un método con el mismo nombre, del objeto Session, con excepción de "all" y "none".

 

<hibernate-mapping package="org.sistema.hibernate.oneToOne.models">
	<class name="Person" table="person">
		<id name="id" column="id">
			<generator class="foreign">
				<param name="property">address</param>
			</generator>
		</id>
		<property name="name" />
		<one-to-one name="address" cascade="persist, delete" />
	</class>
</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Finalmente se crea un fichero hibernate.cfg.xml donde se incluyan los dos XML anteriormente creados (el de Address y Person).

 

 

 

<!-- Here comes the mapping definition - saved in resources dir with this 
			hibernate config -->
<mapping resource="org/sistema/hibernate/oneToOne/mappings/Address.hbm.xml" />
<mapping resource="org/sistema/hibernate/oneToOne/mappings/Person.hbm.xml" />

En este fichero se configurará el nombre de la BD que deberás crear, así como el usuario con permisos para trabajar sobre la misma

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Finalmente se crea un fichero hibernate.cfg.xml donde se incluyan los dos XML anteriormente creados (el de Address y Person).

 

 

 

sesion.persist(address3);
sesion.persist(person1);
sesion.persist(person2);
...
sesion.delete(person1);
Person person1 = new Person();
person1.setName("Persona que sera borrada");

Person person2 = new Person();
person2.setName("Persona que permanecera");

Address address1 = new Address();
address1.setStreet("Calle 1");

Address address2 = new Address();address2.setStreet("Calle 2");

unidad 1: arquitectura del orm

 

eugeniaperez.es

1.2 Configuración del ORM

 

Descarga el proyecto maven_test_annotations del repositorio de Bitbucket:

Usuario: 

Psswd:

URL: https://eugenia_perez@bitbucket.org/eugenia_perez/onetoonexml.git

 

 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

A continuación haremos lo mismo pero con ANOTACIONES. Es decir, prescindiremos de los XML.

Para ello añadiremos la siguiente dependencia el el pom.xml

 

 

 

<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-annotations</artifactId>
		<version>3.5.6-Final</version>
</dependency>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Veamos las anotaciones sobre la clase Address:

 

 

 

@Entity
public class Address {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	private String street;
	private String postCode;

UNIDAD 4: mapeo de clases persistentes

 

4.2 Relaciones 1:1

De la misma forma que antes, indicaremos que existe una relación 1:1 entre Persona y su Dirección.

Análogamente es posible indicar las operaciones que se producirán en cascada: 

 

 

 

@Entity
public class Person {

	@Id
	private long id;

	private String name;

	@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
	private Address address;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Finalmente hacemos referencia desde el fichero de configuración de Hibernate a las dos clases Java.

 

 

 

El resultado debería ser el mismo que el del ejemplo anterior.

 

 

 

<mapping class="org.sistema.hibernate.oneToOne.models.Address" />
<mapping class="org.sistema.hibernate.oneToOne.models.Person" />

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Vamos a ver ahora el mismo caso, pero las relaciones serán BIDIRECCIONALES y no unidireccionales. 

 

 

 

 

 

 

 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

 Especifico el Country.hbm.xml:

 

 

 

 

 

 

 

<hibernate-mapping package="org.sistema.hibernate.oneToOne.models">

	<class name="Country" table="countries">
		<id name="id" column="id">
			<generator class="identity" />
		</id>
		<property name="name" column="name" />
		<one-to-one name="president" cascade="persist,delete" />
</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

 Especifico el President.hbm.xml:

 

 

 

 

 

 

 

<hibernate-mapping package="org.sistema.hibernate.oneToOne.models">
	<class name="President" table="presidents">
		<id name="id" column="id">
			<generator class="foreign">
				<param name="property">country</param>
			</generator>
		</id>

		<property name="name" />
		<one-to-one name="country" constrained="true" />
	</class>
</hibernate-mapping>

No puede existir un Presidente si antes no existe el País que gobernará. 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Veamos cómo sería el mismo ejemplo con anotaciones.

Para la clase Country:

 

 

 

 

 

 

 

@Entity
public class Country {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	private String name;

	@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
	private President president;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Y para la clase President:

 

 

 

 

 

 

 

@Entity
public class President {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	private String name;

	@OneToOne
	private Country country;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.2 Relaciones 1:1

Recuerda añadir los dos ficheros en el fichero de configuración de Hibernate:

 

 

 

 

 

 

 

<mapping class="org.sistema.hibernate.oneToOne.models.Country" />
<mapping class="org.sistema.hibernate.oneToOne.models.President" />

Y todo debería seguir funcionando correctamente...

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Una entidad A está relacionada con muchos objetos de la entidad B.  

 

 

Si es unidireccional solo las personas podrán acceder a los objetos Libros (y no al revés).

 

 

 

 

 

 

 

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Creo un archivo book.hbm.xml:

 

 

 

 

 

 

 

 

 

 

 

eugeniaperez.es

<hibernate-mapping package="org.sistema.hibernate.oneToMany.models">

	<class name="Book" table="books">
		<id name="id">
			<generator class="identity" />
		</id>
		<property name="title" />
	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Creo un archivo person.hbm.xml:

 

 

 

 

 

 

 

 

 

 

 

eugeniaperez.es

<hibernate-mapping package="org.sistema.hibernate.oneToMany.models">

	<class name="Person" table="persons">
		<id name="id" column="idPerson">
			<generator class="identity" />
		</id>
		<property name="name" />
		<list name="books" cascade="all-delete-orphan">
			<key column="idPerson" />
			<index column="book_order" />
			<one-to-many class="Book" />
		</list>

	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Ahora lo pasaremos a clases java con anotaciones.

Clase Book:

 

 

 

 

 

 

 

 

 

 

 

 

eugeniaperez.es

@Entity
public class Book {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	private String title;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Clase Person:

 

 

 

 

 

 

 

 

 

 

 

 

eugeniaperez.es

@Entity
public class Person {
	
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
	private long id;
	private String name;
	
	@OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
	private List<Book> books = new ArrayList<Book>();

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Veremos ahora el mismo ejemplo, pero con relaciones bidireccionales:

 

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

El archivo XML correspondiente a la clase Person queda intacto:

 

eugeniaperez.es

<hibernate-mapping package="org.sistema.hibernate.oneToMany.models">

	<class name="Person" table="persons">
		<id name="id" column="idPerson">
			<generator class="identity" />
		</id>
		<property name="name" />
		<list name="books" cascade="all-delete-orphan">
			<key column="idPerson" />
			<index column="book_order" />
			<one-to-many class="Book" />
		</list>

	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Sin embargo el Book.hbm.xml varía de esta forma:

 

eugeniaperez.es

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.sistema.hibernate.oneToMany.models">

	<class name="Book" table="books">
		<id name="id">
			<generator class="identity" />
		</id>
		<property name="title" />
		<many-to-one name="person" column="idPerson" />
	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Finalmente, cómo sería el mismo ejemplo con anotaciones

Par a la clase Person:

 

eugeniaperez.es

@Entity
public class Person {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	private String name;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, 
mappedBy = "person", orphanRemoval = true)
	private List<Book> books = new ArrayList<Book>();

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.3 Relaciones 1:N

Y para la clase Book:

 

eugeniaperez.es

@Entity
public class Book {

        @Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
	private String title;
	
	@ManyToOne
	private Person person;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

En ocasiones necesitamos relacionar muchas entidades de un tipo con muchas entidades de otro tipo. 

Normalmente los registros en base de datos se relacionan usando una clave foránea de una tabla con el identificador de otra tabla:

 

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

Esto no puede ser logrado utilizando simplemente claves foráneas en las tablas de las entidades A y B. En estos casos se utiliza una tercera tabla conocida como tabla de join, tabla de enlace, o tabla de unión. 

 

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

En nuestro ejemplo relacionaremos Estudiantes con Asignaturas.

Es una N:M unidireccional:

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

Relaciones unidireccionales con archivos de mapeo.

Fichero Subject.hbm.xml:

 

eugeniaperez.es

<hibernate-mapping package="org.sistema.hibernate.manyToMany.models">

	<class name="Subject" table="subjects">
		<id name="id" column="subject_id">
			<generator class="identity" />
		</id>
		<property name="name" />
	</class>

</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

Relaciones unidireccionales con archivos de mapeo.

Fichero Student.hbm.xml:

 

eugeniaperez.es

<hibernate-mapping package="org.sistema.hibernate.manyToMany.models">
	<class name="Student" table="students">
		<id name="id" column="student_id">
			<generator class="identity" />
		</id>
		<property name="name" />
		<list name="subjects" table="students_subjects" cascade="all-delete-orphan">
			<key column="student_id" />
			<list-index column="list_order" />
			<many-to-many class="Subject" column="subject_id" />
		</list>
	</class>
</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

Al final se consiguen tres tablas:

Una para estudiantes:                                      Otra para asignaturas:

 

eugeniaperez.es

...Y una tabla unión:

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Y cómo sería este ejemplo con anotaciones

Esta es la clase Subject

@Entity
public class Subject {

    @Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	private String name;

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Esta es la clase Student

@Entity
public class Student {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;

	private String name;

	@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private List<Subject> subjects = new ArrayList<Subject>();

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Veamos ahora las relaciones N:M bidireccionales

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Con archivos de mapeo:

Date cuenta de que la clase java Student permanece igual, sin embargo en Subject se ha añadido una lista de Students:

 

public class Subject {

	private long id;
	private String name;
	private List<Student> students = new ArrayList<Student>();

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

El fichero Subject.hbm.xml quedaría así:

 

<hibernate-mapping package="org.sistema.hibernate.manyToMany.models">
	<class name="Subject" table="subjects">
		<id name="id" column="subject_id">
			<generator class="identity" />
		</id>
		<property name="name" />
		<list name="students" table="students_subjects" inverse="true">
                        <key column="subject_id" />
			<list-index column="list_order" />
			<many-to-many class="Student" column="student_id" />
		</list>
	</class>
</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Recuerda el fichero Student.hbm.xml que permanece intacto:

 

<hibernate-mapping package="org.sistema.hibernate.manyToMany.models">
	<class name="Student" table="students">
		<id name="id" column="student_id">
			<generator class="identity" />
		</id>
		<property name="name" />
		<list name="subjects" table="students_subjects" cascade="all-delete-orphan">
			<key column="student_id" />
			<list-index column="list_order" />
			<many-to-many class="Subject" column="subject_id" />
		</list>
	</class>
</hibernate-mapping>

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.4 Relaciones N:M

eugeniaperez.es

Finalmente se presenta el mismo ejemplo de N:M bidireccionales con anotaciones:

Student.hbm.xml que permanece intacto:

@Entity
public class Subject {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long id;
	private String name;

	@ManyToMany(mappedBy = "subjects")
	private List<Student> students = new ArrayList<Student>();

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

eugeniaperez.es

En POO la herencia es el mecanismo más utilizado para alcanzar la reutilización y la extensibilidad.

Objetivo: crear nuevas clases partiendo de una clase o de una jerarquía de clases preexistente, evitando el rediseño, la modificación y verificación.

La herencia facilita la creación de objetos a partir de otros ya existentes heredando todo el comportamiento (métodos) y eventualmente los atributos (variables) de su superclase.

 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

eugeniaperez.es

Las tres estrategias de herencia que soporta Hibernate son:

  • Una tabla por toda la jerarquía de clases
  • Una tabla por cada subclase (joins)
  • Una tabla por cada clase concreta (uniones) 

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

eugeniaperez.es

UNIDAD 4: mapeo de clases persistentes

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Tabla por jerarquía de clases

  • Se crea una sola tabla para todas las instancias
  • Con una columna por cada propiedad
  • Se utiliza una columna discriminadora para indicar a qué clase pertenece

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Tabla por jerarquía de clases

Persona.hbm.xml:

<hibernate-mapping>
	<class name="org.sistema.hibernate.inheritanceMappings.models.Persona"
		table="personas">
		<id name="id">
			<generator class="identity" />
		</id>
		<discriminator column="DISC" type="string" />
		<property name="nombre" />
		<property name="edad" />
	</class>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Tabla por jerarquía de clases con ficheros de mapeo

Mapear subclases: Normal.hbm.xml

<hibernate-mapping>
	<subclass name="org.sistema.hibernate.inheritanceMappings.models.Normal"
		discriminator-value="nrm"
		extends="org.sistema.hibernate.inheritanceMappings.models.Persona">
		<property name="ocupacion" />
	</subclass>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

De la misma forma mapearíamos el resto, con distintos discriminadores...

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

En el ejemplo que se expondrá, se crean 5 objetos siendo ésta la tabla

resultante:

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Tabla por jerarquía de clases usando anotaciones

Se utiliza @Inheritance en la raíz de la clase

Con strategy indicamos el tipo de estrategia

Por ejemplo, en la clase Persona:

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DIS", discriminatorType=DiscriminatorType.STRING)
public abstract class Persona implements Serializable
{
}

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

En las otras clases también necesito especificar el discriminador. Por ejemplo, en Tecnólogo:

@Entity
@DiscriminatorValue(value="TC")
public class Tecnologo extends Persona {
	private int aniosDeEstudios;

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Se puede apreciar que la tabla resultante es similar, tras lanzar una aplicación Main similar a la del ejemplo anterior:

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Como podemos ver, con esta estrategia pasamos de nuestra jerarquía de clases a una sola tabla, como se ilustra en la siguiente imagen:

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla para cada subclase -> joins

En esta estrategia de herencia se creará una tabla por cada una de las clases.

 La representación de la relación de herencia entra estas tablas se hace mediante una clave foránea.

Cada tabla contiene solamente las columnas que representan los atributos declarados en la clase, junto con una columna para la clave primaria que es también una clave foránea de la super clase.

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Text

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Las tablas padre y las hijas son unidas por sus claves primarias compartidas.

Es posible recuperar de la base de datos las instancias haciendo un "join" entre dichas tablas.

Ventaja: las modificaciones de una clase no afectan a los datos almacenados de las otras clase (normalización)

Desventaja: las búsquedas debe realizarse en cada una de las tablas de las clases que componen la jerarquía, que en este caso serían 5.  

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla para cada subclase usando ficheros de mapeo

Así queda el fichero Persona.hbm.xml:

 

<hibernate-mapping>
	<class name="org.sistema.hibernate.inheritanceMappings.models.Persona"
		table="personas">
		<id name="id">
			<generator class="identity" />
		</id>
		<property name="nombre" />
		<property name="edad" />
	</class>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla para cada subclase usando ficheros de mapeo

Así queda el fichero Normal.hbm.xml:

 

<hibernate-mapping>
	<joined-subclass
		name="org.sistema.hibernate.inheritanceMappings.models.Normal" table="normales"
		extends="org.sistema.hibernate.inheritanceMappings.models.Persona">
		<key column="id" />
		<property name="ocupacion" />
	</joined-subclass>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Haríamos lo mismo con Tecnólogo. Para las clases que hereden de él, por ejemplo Programador.hbm.xml:

 

<hibernate-mapping>
	<joined-subclass
		name="org.sistema.hibernate.inheritanceMappings.models.Programador"
		table="programadores" 
                extends="org.sistema.hibernate.inheritanceMappings.models.Tecnologo">
		<key column="id" />
		<property name="lenguajeFavorito" />
		<property name="aniosDeExperiencia" />
	</joined-subclass>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Probemos que  funciona correctamente usando el código que teníamos anteriormente en el método "main".. Comprobemos que efectivamente se haya creada una sola tabla para cada una de nuestras clases:

 

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Ahora comprobemos los datos que contiene cada una de las tablas:

 

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla para cada subclase usando anotaciones

En "Persona" usamos la anotación "@Inheritance".

Para usar esta estrategia, lo indicamos en el atributo "strategy" con el valor "InheritanceType.JOINED".

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Persona implements Serializable
{
}

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Ahora veamos el SQL generado con esta estrategia.

Modificamos nuestra aplicación para recuperar el primer "Programador" que guardamos.

Se agrega esta línea al final del método "main":

programadorDAO.find(programador1.getId(), Programador.class);

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

SQL resultante mediante joins:

select programado0_.id as id1_1_0_, 
programado0_2_.edad as edad2_1_0_, 
programado0_2_.nombre as nombre3_1_0_, 
programado0_1_.aniosDeEstudios as aniosDeE1_3_0_, 
programado0_.aniosDeExperiencia as aniosDeE1_2_0_, 
programado0_.lenguajeFavorito as lenguaje2_2_0_ 
from Programador programado0_ 
	inner join Tecnologo programado0_1_ on programado0_.id=programado0_1_.id 
	inner join Persona programado0_2_ on programado0_.id=programado0_2_.id 
where programado0_.id=?

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

¿Pero qué ocurriría si no sabemos exactamente a cuál de las subclases de "Persona" pertenece la entidad? En ese caso:

new GenericDAO<Persona>().find(programador1.getId(), Persona.class);

NO estamos seguros de a cuál clase pertenece el objeto que queremos recuperar (bueno, nosotros sabemos que buscamos un "Pogramador", pero Hibernate solo sabe que busca una subclase de "Persona").

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

4.5 Entidades, herencia y asociaciones

Hibernate genera la siguiente consulta:

select persona0_.id as id1_1_0_, persona0_.edad as edad2_1_0_, persona0_.nombre as nombre3_1_0_, 
persona0_1_.ocupacion as ocupacio1_0_0_, persona0_2_.aniosDeEstudios as aniosDeE1_3_0_, 
persona0_3_.aniosDeExperiencia as aniosDeE1_2_0_, persona0_3_.lenguajeFavorito as lenguaje2_2_0_,
 persona0_4_.herramientaDeTesteo as herramie1_4_0_, 
case 
	when persona0_3_.id is not null then 3 
	when persona0_4_.id is not null then 4 
	when persona0_1_.id is not null then 1 
	when persona0_2_.id is not null then 2 
	when persona0_.id is not null then 0 
end as clazz_0_ 
from Persona persona0_ 
	left outer join Normal persona0_1_ on persona0_.id=persona0_1_.id 
	left outer join Tecnologo persona0_2_ on persona0_.id=persona0_2_.id 
	left outer join Programador persona0_3_ on persona0_.id=persona0_3_.id 
	left outer join Tester persona0_4_ on persona0_.id=persona0_4_.id 
where persona0_.id=?

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Esta estrategia es muy lenta si tenemos consulta en los que no sabemos el tipo concreto de la clase que buscamos, solo la clase base. A estas consultas se les conoce como "Polimórficas".

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta -> uniones

 Se generará una tabla por cada una de las entidades no-abstractas que tenga nuestra aplicación.

Cada tabla tendrá una columna para cada uno de los atributos de la clase de la entidad que almacena, propios y heredados. 

Las tablas no están relacionadas de ninguna forma, por lo que terminaremos con un conjunto de tablas independientes una de otras.

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta -> uniones

 El esquema de la base de

datos será:

 

 

No existe tabla Persona

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta -> uniones

 Esta estrategia tiene la ventaja de que no es necesario hacer un grupo de joins para obtener todos los datos de una entidad, lo que nuevamente nos funciona si haremos consultas SQL a mano.

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando archivos de mapeo

 Indicamos que la clase Persona es abstracta con el atributo abstract de <class>.

<hibernate-mapping>
	<class name="org.sistema.hibernate.inheritanceMappings.models.Persona"
		abstract="true">
		<id name="id">
			<generator class="assigned" />
		</id>
		<property name="nombre" />
		<property name="edad" />
	</class>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando archivos de mapeo

En las subclases en lugar de <class> usaremos <union-subclass> e indicamos de qué clase extiende usando el atributo "extends"

<hibernate-mapping>
	<union-subclass
		name="org.sistema.hibernate.inheritanceMappings.models.Normal" table="normales"
		extends="hibernate.herencia.modelo.Persona">
		<property name="ocupacion" />
	</union-subclass>
</hibernate-mapping>

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Tras ejecutar el main solo se crearon tablas para las entidades no-abstractas de nuestra aplicación. 

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando anotaciones

En esta estrategia hacemos uso de la anotación "@Inheritance" en la clase base ("Persona").

Para indicar el mecanismo de herencia que queremos usar utilizamos el atributo "strategy" con valor: InheritanceType.TABLE_PER_CLASS

En lugar de especificar GenerationType.IDENTITY en el identificador colocaremos GenerationType.TABLE.

 

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando anotaciones

Resultando así la clase Persona:

 

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Persona implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.TABLE)
	private long id;
	private String nombre;
	private int edad;

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando anotaciones

El mapeo de subclases sería idéntico.

Al ejecutar el mismo código Main que el ejemplo anterior, resulta:

 

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Una tabla por cada clase concreta usando anotaciones

Se genera, además de las tablas esperadas, una tabla llamada "hibernate_sequences", usada para generara los identificadores de cada una de las subclases de "Persona" almacenados en la BD.

Como en el caso anterior las búsquedas no suponen un problema si sabemos de qué entidad se trata, pero en caso contrario, habrá que buscar a qué clase pertenece el objeto en todas las tablas para la jerarquía de clases => ¡consultas muy lentas!

UNIDAD 4: MAPEO DE CLASES PERSISTENTES

 

eugeniaperez.es

4.5 Entidades, herencia y asociaciones

Cómo elegir una estrategia de herencia:

  • Si nunca hacemos consultas polimórficas -> opción 3
  • Si sí se hacen consultas polimórficas pero las subclases incluyen pocos atributos -> opción 1
  • Si sí se hacen consultas polimórficas y las subclases incluyen muchos atributos distintos -> opción 2

Por defecto, utilizaremos la opción 3 para problemas simples.

m3-uf2 persistencia con hibernate

 

eugeniaperez.es

FIN DE LA UNIDAD 4: Mapeo de clases persistentes

m3-uf2 persistencia con hibernate

 

eugeniaperez.es

UNIDAD 5: Gestión de objetos persistentes

UNIDAD 5: gestión de objetos persistentes

 

eugeniaperez.es

5.1 Solicitud de objetos con criterios

Hibernate utiliza 3 maneras para recuperar la información:

  • Mediante una query en SQLnativo
  • Creando una query en HQL
  • Con un query a través de Criteria




Made with Slides.com