92
Hibernate / JPA @luce5

Hibernate - JPA @luce 5

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Hibernate - JPA @luce 5

Hibernate / JPA @luce5

Page 2: Hibernate - JPA @luce 5

Embedded

Page 3: Hibernate - JPA @luce 5

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 solicitudeso @Embeddable a la clase dirección (en vez de @Entity)o y @Embedded en el atributo dirección dentro de solicitud.

Page 4: Hibernate - JPA @luce 5

Modos de identidad

Page 5: Hibernate - JPA @luce 5

Modos de identidad

• Identidad de Tabla:o @Ido 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.

Page 6: Hibernate - JPA @luce 5

Modos de identidad

• Por favor, usad una clave subrogada.

• Las claves compuestas sólo dan problemaso Pueden no ser inmutableso Los requisitos cambian y afectan a las claveso Son menos eficientes (ocupan más)o Son menos uniformeso Son incómodas en Java (varios setters)o Son peores en Hibernate

Page 7: Hibernate - JPA @luce 5

Modos de identidad

• Generación:o Identidad (DB2, MySQL, SQL Server...)o Secuenciao Tabla (hi/lo a una tabla)o Autoo 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.

Page 8: Hibernate - JPA @luce 5

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

Page 9: Hibernate - JPA @luce 5

Modos de identidad

• ¿Qué es la identidad?o Identidad de la BDo Identidad de Java

• Para una MISMA sesión, las dos cosas son lo mismo.• Y fuera? Hibernate no garantiza igualdad.

Page 10: Hibernate - JPA @luce 5

Modos de identidad

• Esto es importante en un par de casos sólo:o Composite Primary Key Classo 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.

Page 11: Hibernate - JPA @luce 5

Modos de identidad

• Repetimos...o Si usas primary keys compuestaso 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

Page 12: Hibernate - JPA @luce 5

Modos de locking

Page 13: Hibernate - JPA @luce 5

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.

Page 14: Hibernate - JPA @luce 5

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.

Page 15: Hibernate - JPA @luce 5

Herencia

Page 16: Hibernate - JPA @luce 5

Herencia

• Estrategiaso Tabla por clase concreta

Con polimorfismo implícito Con uniones

o Tabla por jerarquía de claseso Tabla por subclaseo Relaciones polimórficas

• + combinaciones de las anteriores• JPA no soporta todo lo que soporta Hibernate

Page 17: Hibernate - JPA @luce 5

Tabla por clase concreta con polimorfismo implícito

Page 18: Hibernate - JPA @luce 5

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 tablaso El esquema relacional no “conoce” la relacióno No se puede hacer una asociación hacia la abstracta (ya que no es una

entidad)

Page 19: Hibernate - JPA @luce 5

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

Page 20: Hibernate - JPA @luce 5

Tabla por clase concreta con uniones

Page 21: Hibernate - JPA @luce 5

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

Page 22: Hibernate - JPA @luce 5

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

Page 23: Hibernate - JPA @luce 5

Tabla por jerarquía

Page 24: Hibernate - JPA @luce 5

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

Page 25: Hibernate - JPA @luce 5

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

Page 26: Hibernate - JPA @luce 5

Tabla por subclase

Page 27: Hibernate - JPA @luce 5

Tabla por subclase

• Basada en FKs

• Esquema normalizado

• Contrapartidas…o Complica el esquemao Ineficiente en jerarquías complejas*o Clase padre concreta

Page 28: Hibernate - JPA @luce 5

Tabla por subclase

@Entity

@Inheritance(strategy = InheritanceType.JOINED)

public abstract class AbstractPago

@Entity

public class PagoPAC extends AbstractPago

@Entity

public class PagoBeca extends AbstractPago

Page 29: Hibernate - JPA @luce 5

Limitaciones de herencia

• Limitaciones oficiales

• Implementad alguna!o session.createCriteria(Petition.class) .list();

Page 30: Hibernate - JPA @luce 5

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 FKso Envers no lo soporta ☹

Page 31: Hibernate - JPA @luce 5

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() {

Page 32: Hibernate - JPA @luce 5

Mapeos 'complejos'

Page 33: Hibernate - JPA @luce 5

Mapeos 'complejos'

• @SecondaryTables + @SecondaryTable + @PrimaryKeyJoinColumn

• @Parent

• @Target

• @NotFound

Page 34: Hibernate - JPA @luce 5

Batch Processing

Page 35: Hibernate - JPA @luce 5

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();

Page 36: Hibernate - JPA @luce 5

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

Page 37: Hibernate - JPA @luce 5

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();

Page 38: Hibernate - JPA @luce 5

Batch Processing

• Stateless Sessiono Sin caché de primer nivelo Sin caché de segundo nivelo Sin dirty checking/write behindo Sin cascadeso Sin interceptoreso Similar a JDBC

• Scrollable• HQL

Page 39: Hibernate - JPA @luce 5

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.

Page 40: Hibernate - JPA @luce 5

Servicios

Page 41: Hibernate - JPA @luce 5

Servicios

• Un sistema de extensión (similar a plugins) de Hibernate.o Desde Hibernate 4.0o Permite el registro de servicios/implementaciones alternativas para, por

ejemplo: TransactionFactory (transacciones) JtaPlatform (gestión de JTA) JndiService JdbcServices ConfigurationService ...

Page 42: Hibernate - JPA @luce 5

Transitividad (cascades)

Page 43: Hibernate - JPA @luce 5

Transitividad

• Cascades de JPA:o CascadeType.PERSIST: cascada de persistso CascadeType.MERGE: cascadas de mergeso CascadeType.REMOVE: cascade de eliminacioneso 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

Page 44: Hibernate - JPA @luce 5

Transitividad

• Cascades de Hibernate (@Cascade):o save-update...o deleteo locko replicate (copiar un objeto, muy muy raro)o evicto delete-orphan

Page 45: Hibernate - JPA @luce 5

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!

Page 46: Hibernate - JPA @luce 5

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 orphanRemovalo Típicos: persist, save-update...

Page 47: Hibernate - JPA @luce 5

Caching

Page 48: Hibernate - JPA @luce 5

Caching

• Caché de primer nivelo get() y load() me recuperan objetos que tienen en la sesión...

• Caché de segundo nivel

• Caché de querieso 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.

Page 49: Hibernate - JPA @luce 5

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)

Page 50: Hibernate - JPA @luce 5

Caching

• Tipos de Caching:o NONEo READ_ONLY: no se modifican a menudo...o NONSTRICT_READ_WRITE: pocas transacciones apuntando al mismo

item...o READ_WRITE: actualizaciones frecuentes.o TRANSACTIONAL

Page 51: Hibernate - JPA @luce 5

Caching

• Típicos proveedores:o EHCache: soporta todos los tipos de cachingo Infinispan: read-only, transactional

Page 52: Hibernate - JPA @luce 5

Caching

• Queries:o Activar use_query_cacheo Establecer el tiempo de timeouto Establecer las queries que quieres cachear

setCacheable(true)

Page 53: Hibernate - JPA @luce 5

Performance

Page 54: Hibernate - JPA @luce 5

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+1o Fetch-profiles (para personalizar escenarios de búsqueda)o Personalizar Fetch en Criterias

(criteria.setFetchMode("propiedad",MODO)) EAGER=JOIN, LAZY=SELECT Probadlo!"

Page 55: Hibernate - JPA @luce 5

Performance

• Tres grandes tipos de colecciones:o indexed collections (mapas, listas, arrays)o setso 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

Page 56: Hibernate - JPA @luce 5

Performance

• One-shot-deleteo Imaginemos que tenemos 20 elementos, eliminamos 18 y añadimos 3o Podemos borrar 18 elementos (1 a 1) e insertar 3o Eliminar todo e insertar 5

En este caso conviene hacer clear();

• Probadlo!

Page 57: Hibernate - JPA @luce 5

Performance

• Marcar claves naturales @NaturalId (puede mejorar rendimiento al acceder a ellas)

• Realizar mapeos sencillos (los que hemos visto)

Page 58: Hibernate - JPA @luce 5

Performance

• Si realiza muchas consultas:o plantear estrategias estilo JOIN/SUBSELECTo Activar batch o utilizar @BatchSizeo Activar caché de segundo nivelo HQLo SQLo Query cache

Page 59: Hibernate - JPA @luce 5

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 Índiceso HQLo SQLo Query cache

Page 60: Hibernate - JPA @luce 5

Validaciones

Page 61: Hibernate - JPA @luce 5

Validaciones

• Hibernate se complementa con Hibernate Validator

• Es la base de Bean Validation, un estándar Java EE 6o @NotNull

o @Past

o @Size

o @Pattern

o @Max

o @Email

o @CreditCardNumber

Page 62: Hibernate - JPA @luce 5

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!

Page 63: Hibernate - JPA @luce 5

Envers

Page 64: Hibernate - JPA @luce 5

Envers

• Librería de auditoría.• Para activar la versión "básica" basta con:

o Copiar la libreríao @Auditedo Cuidado con relaciones: @NotAudited (de momento)

• Probadlo!

Page 65: Hibernate - JPA @luce 5

Envers

• Puedo hacer queries específicas:

AuditQuery query = AuditReaderFactory.get(session)

.createQuery()

.forEntitiesAtRevision(MyEntity.class, revisionNumber);

query.uni../getResu..()

• Probadlo!

Page 66: Hibernate - JPA @luce 5

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();

Page 67: Hibernate - JPA @luce 5

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!

Page 68: Hibernate - JPA @luce 5

Envers

• Envers es más quisquilloso en algún tipo concreto de mapeos:o Bagso @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.

Page 69: Hibernate - JPA @luce 5

Multi-tenancy

Page 70: Hibernate - JPA @luce 5

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 datoso Base de datos diferente, JDBC que cambiao Esquema separado, schema que cambia al conectarseo Única base de datos, discriminador

Page 71: Hibernate - JPA @luce 5

Multi-tenancy

• En Hibernate:Session session = sessionFactory.withOptions()

.tenantIdentifier( yourTenantIdentifier )

.openSession();

• Opciones de identificador:o DATABASEo SCHEMAo DISCRIMINATOR (No soportada aún, Hibernate 5)

Page 72: Hibernate - JPA @luce 5

¿Qué más es Hibernate?

Page 73: Hibernate - JPA @luce 5

¿ Qué más es Hibernate?

Page 74: Hibernate - JPA @luce 5

¿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

Page 75: Hibernate - JPA @luce 5

Recomendaciones y errores habituales

Page 76: Hibernate - JPA @luce 5

Recomendaciones

• No utilices claves compuestaso 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

Page 77: Hibernate - JPA @luce 5

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.

Page 78: Hibernate - JPA @luce 5

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_transo -> OpenSessionInViewo -> Conversaciones

Page 79: Hibernate - JPA @luce 5

Errores típicos

• Detached entity passed to persist, causado por:o Fijar un id manualmente a una entidad que utiliza un auto-generadoo 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.

Page 80: Hibernate - JPA @luce 5

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 directamenteo -> usa save()

Page 81: Hibernate - JPA @luce 5

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 existeo Modificaciones en paralelo de la coleccióno 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

Page 82: Hibernate - JPA @luce 5

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...

Page 83: Hibernate - JPA @luce 5

Recapitulando...

Page 84: Hibernate - JPA @luce 5

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

Page 85: Hibernate - JPA @luce 5

Recapitulando...

• ¿Cómo se busca y ordena?o Criteria, HQL, SQL, anotaciones...

• ¿Cómo se recuperan objetos con asociaciones?o @OneToMany... fetches

Page 86: Hibernate - JPA @luce 5

Recapitulando...

• Preguntas de exameno 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 sesioneso Session? Threadsafe? -> no...o sorted/ordered collections? -> ordenada en memoria o no

Page 87: Hibernate - JPA @luce 5

Recapitulando...

• Preguntas de exameno transient/persistent/detached? -> estados de la entidado session.lock()? -> marcar entidad buena, bloquear BDo second level cache? ->o Constructor sin argumentos? -> no sabe qué crear...o Hibernate Entity Class Final? -> es malo por rendimientoo lazy initialization exception? -> o N+1 selects? ->

Page 88: Hibernate - JPA @luce 5

Conclusiones

Page 89: Hibernate - JPA @luce 5

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/actualizacioneso Otra herramienta/capa máso 'Mapeos complejos'o Conflictiva si no la usas bieno ...

Page 90: Hibernate - JPA @luce 5

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 cascadao Navegacióno Mapea una vez → CRUD completo

• Separación de responsabilidades• Valor añadido (validación, envers...)

Page 91: Hibernate - JPA @luce 5

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óno Separación de lógica y datoso …

• … “(…) the main thing is to be practical and stop paying too much attention to lame patterns talk.”

Page 92: Hibernate - JPA @luce 5

Hibernate / JPA