Hibernate - JPA @luce 5

1,715 views

Published on

Last session of the Hibernate course, about embedded, locking behaviour, inheritance...

5/5

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,715
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
38
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Hibernate - JPA @luce 5

  1. 1. Hibernate / JPA @luce5
  2. 2. Embedded
  3. 3. Embedded • • • Clases que no tienen relación directa con una tabla (están contenidas dentro de otra tabla) o Ejemplo clásico: Usuario y dirección. Para mapear, @Embeddable para indicar que una clase se puede incluir dentro de otra y @Embedded para incluir dentro de una clase. Añadid dirección a las solicitudes o @Embeddable a la clase dirección (en vez de @Entity) o y @Embedded en el atributo dirección dentro de solicitud.
  4. 4. Modos de identidad
  5. 5. Modos de identidad • • Identidad de Tabla: o @Id o Compuesto:  Varios @Id  @EmbeddedId (clase con @Embeddable y referencia con @EmbeddedId)  Id en otra clase y @IdClass en la tabla Probad cualquiera de estas referencias.
  6. 6. Modos de identidad • • Por favor, usad una clave subrogada. Las claves compuestas sólo dan problemas o Pueden no ser inmutables o Los requisitos cambian y afectan a las claves o Son menos eficientes (ocupan más) o Son menos uniformes o Son incómodas en Java (varios setters) o Son peores en Hibernate
  7. 7. Modos de identidad • • • Generación: o Identidad (DB2, MySQL, SQL Server...) o Secuencia o Tabla (hi/lo a una tabla) o Auto o 14 algoritmos más En base a @GeneratedValue y seleccionando la estrategia y el generador (@SequenceGenerator, entre otros). Probad @SequenceGenerator para ver las opciones de configuración.
  8. 8. Modos de identidad • Además de un @Id puedes definir que una columna es un Id Natural: o … @NaturalId o buscar por natural id bySimpleNaturalId
  9. 9. Modos de identidad • • • ¿Qué es la identidad? o Identidad de la BD o Identidad de Java Para una MISMA sesión, las dos cosas son lo mismo. Y fuera? Hibernate no garantiza igualdad.
  10. 10. Modos de identidad • • Esto es importante en un par de casos sólo: o Composite Primary Key Class o 2 instancias de la misma clase en un Set en sesiones diferentes Implementa equals y hashCode, teniendo en cuenta que dos objetos diferentes pueden representar el mismo objeto en la base de datos.
  11. 11. Modos de identidad • • • Repetimos... o Si usas primary keys compuestas o O si quieres unir entidades detached (luego veremos que es...) que reúsas en un Set Deberías implementar equals y hashCode: o Comparando por igualdad de negocio (columnas y valores que identifican univocamente a una entidad) https://community.jboss.org/wiki/EqualsAndHashCode
  12. 12. Modos de locking
  13. 13. Modos de locking • • • • Hasta ahora, sin saberlo, estamos trabajando con un modo last commit wins. Cuando vamos a trabajar con algo, Hibernate recupera la entidad de la base de datos. Si cuando guardamos los datos han cambiado, ese usuario pierde esa información. Podemos trabajar de forma optimista, al guardar Hibernate comprueba que no se han tocado las cosas. Si se han tocado da un error, si no, sigue con su trabajo.
  14. 14. Modos de locking • Para activarlo, sólo tenemos que definir un atributo de tipo Integer anotado con @Version. o Podemos usar un Date también • Probadlo! • • En cualquier momento podemos llamar a un lock pesimista con session.lock() [Avanzado] Si tenéis tiempo... bloquead la inserción de una tabla.
  15. 15. Herencia
  16. 16. Herencia • • • Estrategias o Tabla por clase concreta  Con polimorfismo implícito  Con uniones o Tabla por jerarquía de clases o Tabla por subclase o Relaciones polimórficas + combinaciones de las anteriores JPA no soporta todo lo que soporta Hibernate
  17. 17. Tabla por clase concreta con polimorfismo implícito
  18. 18. Tabla por clase concreta con polimorfismo implícito • • Es simple, consultar contra clases concretas Contrapartidas… o Polimorfismo  Requiere una consulta por cada subclase concreta  Las asociaciones no se representan bien (no aceptan una FK simple) o Semánticas compartidas entre tablas o El esquema relacional no “conoce” la relación o No se puede hacer una asociación hacia la abstracta (ya que no es una entidad)
  19. 19. Tabla por clase concreta con polimorfismo implícito @MappedSuperclass public abstract class AbstractPago @Entity public class PagoPAC extends AbstractPago @Entity public class PagoBeca extends AbstractPago
  20. 20. Tabla por clase concreta con uniones
  21. 21. Tabla por clase concreta con uniones • Permite relaciones hacia la clase abstracta • Consultas optimizables por el SGBD • Contrapartidas… o El esquema relacional no “conoce” la relación
  22. 22. Tabla por clase concreta con uniones @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class AbstractPago @Entity public class PagoPAC extends AbstractPago @Entity public class PagoBeca extends AbstractPago
  23. 23. Tabla por jerarquía
  24. 24. Tabla por jerarquía • La mejor para el polimorfismo y para no polimorfismo • Contrapartidas… o Requiere columnas nullables en las subclases o Posible desperdicio de espacio o Requiere discriminador
  25. 25. Tabla por jerarquía @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="tipo", discriminatorType=DiscriminatorType.STRING) public abstract class AbstractPago @Entity @DiscriminatorValue("PAC") public class PagoPAC extends AbstractPago @Entity @DiscriminatorValue("beca") public class PagoBeca extends AbstractPago
  26. 26. Tabla por subclase
  27. 27. Tabla por subclase • Basada en FKs • Esquema normalizado • Contrapartidas… o Complica el esquema o Ineficiente en jerarquías complejas* o Clase padre concreta
  28. 28. Tabla por subclase @Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class AbstractPago @Entity public class PagoPAC extends AbstractPago @Entity public class PagoBeca extends AbstractPago
  29. 29. Limitaciones de herencia • • Limitaciones oficiales Implementad alguna! o session.createCriteria(Petition.class) .list();
  30. 30. Relaciones polimórficas • • • Permite mapear relaciones que no se podrían de otra forma: asociaciones polimórficas a clases desde múltiples tablas Sólo para situaciones muy especiales Contrapartidas… o No puede establecer FKs o Envers no lo soporta ☹
  31. 31. Relaciones polimórficas public interface Cosa @Entity public class Beca implements Cosa @Entity public class Pago implements Cosa @Any(metaColumn = @Column(name = "tipo_de_cosa")) @AnyMetaDef(idType = "long", metaType = "string", metaValues = { @MetaValue(value = "Beca", targetEntity = Beca.class), @MetaValue(value = "Pago", targetEntity = Pago.class) }) @JoinColumn(name = "tipo_de_cosa_id") public Cosa getCosa() {
  32. 32. Mapeos 'complejos'
  33. 33. Mapeos 'complejos' • @SecondaryTables + @SecondaryTable + @PrimaryKeyJoinColumn • @Parent • @Target • @NotFound
  34. 34. Batch Processing
  35. 35. Batch Processing • ¿Qué pasa si lanzamos esto? Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Petition petition = new Petition(.....); session.save(petition); } tx.commit(); session.close();
  36. 36. Batch Processing • • Hibernate se queda sin memoria. Podemos arreglarlo, haciendo operaciones en batch: o Activando hibernate.jdbc.batch_size (en persistence/hibernate.cfg.xml) y poniendolo a un valor entre 10-50
  37. 37. Batch Processing Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Petition petition = new Petition(.....); session.save(petition); if ( i % 20 == 0 ) { //el valor de la propiedad session.flush(); session.clear(); } } tx.commit(); session.close();
  38. 38. Batch Processing • • • Stateless Session o Sin caché de primer nivel o Sin caché de segundo nivel o Sin dirty checking/write behind o Sin cascades o Sin interceptores o Similar a JDBC Scrollable HQL
  39. 39. Batch Processing • • En estrategias de Fetch hay una adicional (cuarta) o @BatchSize, recupera sentencias en bloque. MUY interesante... o soluciona el problema de los N+1 fetches.
  40. 40. Servicios
  41. 41. Servicios • Un sistema de extensión (similar a plugins) de Hibernate. o Desde Hibernate 4.0 o Permite el registro de servicios/implementaciones alternativas para, por ejemplo:  TransactionFactory (transacciones)  JtaPlatform (gestión de JTA)  JndiService  JdbcServices  ConfigurationService  ...
  42. 42. Transitividad (cascades)
  43. 43. Transitividad • Cascades de JPA: o CascadeType.PERSIST: cascada de persists o CascadeType.MERGE: cascadas de merges o CascadeType.REMOVE: cascade de eliminaciones o CascadeType.REFRESH: cascade de refresh (volver a leer una entidad de BD) o CascadeType.DETACH: cascade de detach (desunir de sesión) o CascadeType.ALL: todos los de arriba
  44. 44. Transitividad • Cascades de Hibernate (@Cascade): o save-update... o delete o lock o replicate (copiar un objeto, muy muy raro) o evict o delete-orphan
  45. 45. Transitividad • • Delete orphan es interesante: o Sólo aplica a oneToMany. o Cuando elimino un elemento hijo de la colección indico que quiero eliminarlo de la BD porque se ha quedado huérfano. o orphanRemoval en @OneToMany.  No estoy haciendo esto: session.remove()  padre.geHijos().remove(0) o No cuenta para Cascade.ALL. o @OneToMany(orphanRemoval = true) Probadlo!
  46. 46. Transitividad • Recomendaciones de cascade: o Es más lógico en relaciones @OneToOne y @OneToMany (padre con hijos) o Si el objeto hijo en un @OneToMany no tiene sentido sin el padre -> Cascade.ALL y orphanRemoval o Típicos: persist, save-update...
  47. 47. Caching
  48. 48. Caching • • • Caché de primer nivel o get() y load() me recuperan objetos que tienen en la sesión... Caché de segundo nivel Caché de queries o Hibernate tiene en cuenta cambios en los objetos que se muestran en las consultas. o Depende del patrón de uso de la aplicación.
  49. 49. Caching • Caché de segundo nivel: o Muy común, Hibernate se integra muy bien con varios proveedores de caché. o Típico para tablas de referencia (provincia, localidad, datos maestros...) o Marcar entidades interesadas (o colecciones): @Cacheable o @Cache(usage = CacheConcurrencyStrategy.TIPO_DE_CACHING)
  50. 50. Caching • Tipos de Caching: o NONE o READ_ONLY: no se modifican a menudo... o NONSTRICT_READ_WRITE: pocas transacciones apuntando al mismo item... o READ_WRITE: actualizaciones frecuentes. o TRANSACTIONAL
  51. 51. Caching • Típicos proveedores: o EHCache: soporta todos los tipos de caching o Infinispan: read-only, transactional
  52. 52. Caching • Queries: o Activar use_query_cache o Establecer el tiempo de timeout o Establecer las queries que quieres cachear  setCacheable(true)
  53. 53. Performance
  54. 54. Performance • • Hibernate no es lento. Recomendaciones de rendimiento: o Tener en cuenta las 4 estrategias de fetching (Select, Subselect, Join, BatchSize) o Cuidado con N+1 o Fetch-profiles (para personalizar escenarios de búsqueda) o Personalizar Fetch en Criterias (criteria.setFetchMode("propiedad",MODO)) EAGER=JOIN, LAZY=SELECT  Probadlo!"
  55. 55. Performance • • • Tres grandes tipos de colecciones: o indexed collections (mapas, listas, arrays) o sets o bags Las dos primeras son las más eficientes en save/remove/update de elementos. Bags y lists son más eficientes en @OneToMany con mappedBy
  56. 56. Performance • • One-shot-delete o Imaginemos que tenemos 20 elementos, eliminamos 18 y añadimos 3 o Podemos borrar 18 elementos (1 a 1) e insertar 3 o Eliminar todo e insertar 5  En este caso conviene hacer clear(); Probadlo!
  57. 57. Performance • • Marcar claves naturales @NaturalId (puede mejorar rendimiento al acceder a ellas) Realizar mapeos sencillos (los que hemos visto)
  58. 58. Performance • Si realiza muchas consultas: o plantear estrategias estilo JOIN/SUBSELECT o Activar batch o utilizar @BatchSize o Activar caché de segundo nivel o HQL o SQL o Query cache
  59. 59. Performance • Si realiza una consulta muy pesada: o Eliminar cruces JOIN (empezando por colecciones) o Poner asociaciones *ToOne a Lazy (con Select o Subselect) o Índices o HQL o SQL o Query cache
  60. 60. Validaciones
  61. 61. Validaciones • • Hibernate se complementa con Hibernate Validator Es la base de Bean Validation, un estándar Java EE 6 o @NotNull o @Past o @Size o @Pattern o @Max o @Email o @CreditCardNumber
  62. 62. Validaciones • • Incluid las librerías de validation (es más sencillo en Java EE) o Añadid una anotación y probad a guardar. Podemos llamar a los validadores con: ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<User>> constraintViolations = validator.validate(user); • Probadlo!
  63. 63. Envers
  64. 64. Envers • • • Librería de auditoría. Para activar la versión "básica" basta con: o Copiar la librería o @Audited o Cuidado con relaciones: @NotAudited (de momento) Probadlo!
  65. 65. Envers • Puedo hacer queries específicas: AuditQuery query = AuditReaderFactory.get(session) .createQuery() .forEntitiesAtRevision(MyEntity.class, revisionNumber); query.uni../getResu..() • Probadlo!
  66. 66. Envers • Dos estrategias, start y start-end • Puedo guardar el usuario o información adicional • Las querys pueden llegar a ser complejas: List personsAtAddress = getAuditReader().createQuery() .forEntitiesAtRevision(Person.class, 12) .addOrder(AuditEntity.property("surname").desc()) .add(AuditEntity.relatedId("address").eq(addressId)) .setFirstResult(4) .setMaxResults(2) .getResultList();
  67. 67. Envers • Puedo preguntar a una entidad por las revisiones que ha tenido Number revision = (Number) getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) .setProjection(AuditEntity.revisionNumber().min()) .add(AuditEntity.id().eq(entityId)) .add(AuditEntity.revisionNumber().gt(42)) .getSingleResult(); • Probadlo!
  68. 68. Envers • • Envers es más quisquilloso en algún tipo concreto de mapeos: o Bags o @OneToMany+@JoinColumn, mappedBy (necesita @AuditJoinTable) o @OneToMany+@JoinColumn, insertable=false, updatable = false (necesita @AuditMappedBy) Siempre se puede decidir no auditar una relación con @NotAudited.
  69. 69. Multi-tenancy
  70. 70. Multi-tenancy • Una aplicación que sirve múltiples clientes. • Típico de SaaS (Software as Service: google docs) • Cada cliente sólo debe poder ver sus datos o Base de datos diferente, JDBC que cambia o Esquema separado, schema que cambia al conectarse o Única base de datos, discriminador
  71. 71. Multi-tenancy • • En Hibernate: Session session = sessionFactory.withOptions() .tenantIdentifier( yourTenantIdentifier ) .openSession(); Opciones de identificador: o DATABASE o SCHEMA o DISCRIMINATOR (No soportada aún, Hibernate 5)
  72. 72. ¿Qué más es Hibernate?
  73. 73. ¿ Qué más es Hibernate?
  74. 74. ¿Qué más es Hibernate? • • • • • • • • • • Core Shards: fragmentación horizontal Search: búsqueda de texto completo (Lucene) Tools Validator: validación de datos Metamodel Generator OGM Annotations Entity Manager: operaciones y ciclo JPA Envers: versionado e histórico
  75. 75. Recomendaciones y errores habituales
  76. 76. Recomendaciones • • No utilices claves compuestas o Claves surrogadas siempre, ni naturales ni compuestas En el import.sql (ficheros sql que carga Hibernate directamente), los ids, negativos (para no hacer conflicto con ids generados) • No uses herencia, usa agregación (GoF) • No uses mapas, usa entidades y relaciones
  77. 77. Recomendaciones • • • • Cuando estés mapeando por primera vez, hacer tests (incluso vacíos) está bien: o No arrancas el servidor de aplicaciones! Ojo con los "lazos" en los modelos y las relaciones bidireccionales... Se puede implementar SoftDelete (@SQLDelete) o restricciones globales de búsqueda (@Where) Puedo ver los valores de las consultas (?) -> en log4j, org.hibernate.type a TRACE.
  78. 78. Errores típicos • Lazy Initialization Exception, causado por: o Intentar cargar desde la vista/lógica con la sesión cerrada una lista de objetos/objeto con fetch a LAZY. o -> Hibernate.initialize() o -> Activar lazy load sin transacciones: hibernate.enable_lazy_load_no_trans o -> OpenSessionInView o -> Conversaciones
  79. 79. Errores típicos • • Detached entity passed to persist, causado por: o Fijar un id manualmente a una entidad que utiliza un auto-generado o Sin cascadas, intentar guardar una relación de un objeto que no está en la base de datos. o Llamada persist() o save() de un objeto que ya está en la BD Cannot Open Connection, causado por: o Malos valores de conexión a la BD.
  80. 80. Errores típicos • • • NPE en IntegerType.next(IntegerType.java:82), causado por: o Número de versión (@version) nulo Collection was not processed by flush, causado por (varios motivos, peliagudo): o Envers, bags y malas anotaciones de envers. o Jugar con las listas (utilizar add() a veces y sustituir las listas enteras al mismo tiempo). Llamo a persist() y no tengo id, causado por: o persist() no asigna el id directamente o -> usa save()
  81. 81. Errores típicos • • No row with the given identifier exists (uff), causado por: o Hay una entidad que apunta a una fila de la BD que ya no existe o Modificaciones en paralelo de la colección o Cascades delete/eliminaciones de elementos de la colección sin actualizar el otro lado de la relación. Hibernate me devuelve datos duplicados Relaciones bidireccionales mal mapeadas Cruces cartesianos sin Distinct.ROOT_ENTITY • •
  82. 82. Errores típicos • A collection with cascade delete-orphan was no longer referenced... o Mala gestión de las colecciones: Coleccion coleccion = miEntidad.getColeccion(); Coleccion coleccionNueva = new ColeccionImpl(coleccion); miEntidad.setColeccion(coleccionNueva); • o -> add() De principiante (y no tanto): constructor, @Entity, @Id...
  83. 83. Recapitulando...
  84. 84. Recapitulando... • • • • • ¿Cómo es una clase persistente, una entidad? o @Entity y @Id (Constructor [Serializable]) ¿Cómo se especifica los metadatos de mapeos? o Anotaciones | XML @OneToMany... ¿Qué relación hay entre identidad de objetos y de base de datos? o Dentro de una sesión, son lo mismo. Si hay objetos detached -> no. ¿Qué tipos de herencia hay? o 4 -> tablas única, 2 tablas (2), 3 tablas ¿Cuál es el ciclo de vida de un objeto persistente? o Persistent -> Detached. Transient nuevo, Delete a eliminar
  85. 85. Recapitulando... • • ¿Cómo se busca y ordena? o Criteria, HQL, SQL, anotaciones... ¿Cómo se recuperan objetos con asociaciones? o @OneToMany... fetches
  86. 86. Recapitulando... • Preguntas de examen o get() y load() -> Hibernate | JPA (lazy) o save() / persist() / saveOrUpdate() -> = que antes, diferencias en tratamiento en id. o named SQL Query? -> query definida para reusar. o SessionFactory? -> objeto único.. thread safe me da sesiones o Session? Threadsafe? -> no... o sorted/ordered collections? -> ordenada en memoria o no
  87. 87. Recapitulando... • Preguntas de examen o transient/persistent/detached? -> estados de la entidad o session.lock()? -> marcar entidad buena, bloquear BD o second level cache? -> o Constructor sin argumentos? -> no sabe qué crear... o Hibernate Entity Class Final? -> es malo por rendimiento o lazy initialization exception? -> o N+1 selects? ->
  88. 88. Conclusiones
  89. 89. Ventajas e inconvenientes de los ORMs • Ideas? o Te olvidas de la base de datos (buscar inserts o updates modificados) o Y del SGBD (usando estándar SQL) o Simplifica la gestión de inserciones/actualizaciones o Otra herramienta/capa más o 'Mapeos complejos' o Conflictiva si no la usas bien o ...
  90. 90. Ventajas de los ORMs • • • • • Diseño Orientado al Objeto puro (con pegas) Separación de lógica y datos → Java EE, EJBs... Productividad o Operaciones en cascada o Navegación o Mapea una vez → CRUD completo Separación de responsabilidades Valor añadido (validación, envers...)
  91. 91. Inconvenientes de los ORMs • • • • • Necesitas conocimientos de SQL Conviene “olvidarse del modelo” → modelo relacional “incorrecto”. Se delega el control de las consultas Modelo de dominio anémico o Exposición de la implementación o Separación de lógica y datos o … … “(…) the main thing is to be practical and stop paying too much attention to lame patterns talk.”
  92. 92. Hibernate / JPA

×