Hibernate.orgCommunity Documentation

Capítulo 27. Prácticas recomendadas

Escriba las clases detalladas y mapéelas utilizando <component>:

Utilice una clase Dirección para encapsular calle, distrito, estado, código postal. Esto promueve la reutilización de código y simplifica la refabricación.

Declare las propiedades identificadoras en clases persistentes:

Las propiedades identificadoras son opcionales en Hibernate. Existe todo tipo de razones por las que debe usarlas. Recomendamos que los identificadores sean 'sintéticos', es decir, generados sin ningún significado empresarial.

Identifique las llaves naturales:

Identifique las claves naturales de todas las entidades, y mapéelas usando <natural-id>. Implemente equals() y hashCode() para comparar las propiedades que componen la clave natural.

Coloque cada mapeo de clase en su propio fichero:

No use un sólo documento monolítico de mapeo. Mapee com.eg.Foo en el archivo com/eg/Foo.hbm.xml. Esto tiene sentido particularmente en un entorno de equipo.

Cargue los mapeos como recursos:

Despliegue los mapeos junto a las clases que mapean.

Considere el externalizar las cadenas de petición:

Esta es una buena práctica si sus consultas llaman a funciones SQL que no son del estándar ANSI. Externalizar las cadenas de consulta a archivos de mapeo hará la aplicación más portátil.

Use variables de vinculación.

Al igual que en JDBC, siempre remplace los valores no constantes con "?". No use la manipulación de cadenas para enlazar un valor no constante en una consulta. También considere utilizar parámetros con nombre en las consultas.

No administre sus propias conexiones JDBC:

Hibernate deja a la aplicación administrar las conexiones JDBC, pero este enfoque debe considerarse como el último recurso. Si no puede utilizar los provedores de conexión incorporados, considere proveer su propia implementación de org.hibernate.connection.ConnectionProvider.

Considere utilizar un tipo personalizado:

Supónga que tiene un tipo Java de una biblioteca, que necesita hacerse persistente pero que no provee los métodos de acceso necesarios para mapearlo como un componente. Debe considerar el implementar org.hibernate.UserType. Este enfoque libera al código de aplicación de implementar transformaciones a/desde un tipo Hibernate.

Utilice JDBC codificado a mano cuando se encuentre atascado:

En áreas de rendimiento crítico del sistema, algunos tipos de operaciones podrían beneficiarse del JDBC directo. Sin embargo, no asuma que JDBC es necesariamente más rápido. Por favor, espere hasta que sepa que se encuentra realmente atascado. Si necesita utilizar JDBC directo, puede abrir una Session de Hibernate, envuelva su operación JDBC como un objeto org.hibernate.jdbc.Work usando esa conexión JDBC. De esta manera puede usar aún la misma estrategia de transacción y el mismo proveedor de conexiones subyacente.

Comprenda el vaciado de Session:

A veces la sesión sincroniza su estado persistente con la base de datos. El rendimiento se verá afectado si este proceso ocurre con demasiada frecuencia. A veces puede minimizar el vaciado innecesario deshabilitando el vaciado automático o incluso cambiando el orden de las consultas u otras operaciones en una transacción en particular.

En una arquitectura con tres niveles considere el utilizar objetos separados:

Al usar una arquitectura de servlet/sesión, puede pasar objetos persistentes en el bean de sesión hacia y desde la capa del servlet/JSP. Use una sesión nueva para atender el servicio de cada petición. Use Session.merge() o Session.saveOrUpdate() para sincronizar los objetos con la base de datos.

En una arquitectura con dos niveles considere el utilizar contextos largos de persistencia:

Las transacciones de la base de datos tienen que ser tan cortas como sea posible para obtener una mejor escalabilidad. Sin embargo, con frecuencia es necesario implementar transacciones de aplicación de larga ejecución, una sola unidad de trabajo desde el punto de vista de un usuario. Una transacción de aplicación puede abarcar muchos ciclos de petición/respuesta del cliente. Es común usar objetos separados para implementar transacciones de aplicación. Una alternativa apropiada en arquitecturas de dos niveles, es mantener una sesión de un sólo contacto de persistencia abierto para todo el ciclo de vida de la transacción de aplicación. Luego simplemente desconectar de la conexión JDBC al final de cada petición y reconectar al comienzo de la petición subsecuente. Nunca comparta una sesión única a través de más de una transacción de aplicación o estará trabajando con datos desactualizados.

No trate las excepciones como recuperables:

Esto es más bien una práctica necesaria más que una práctica "recomendada". Cuando ocurra una excepción, deshaga la Transaction y cierre la Session. Si no lo hace, Hibernate no puede garantizar que el estado en memoria representa con exactitud el estado persistente. Por ejemplo, no utilice Session.load() para determinar si una instancia con el identificador dado existe en la base de datos; en cambio, use Session.get() o una consulta.

Prefiera una recuperación perezosa para las asociaciones:

No utilice con frecuencia la recuperación temprana. Use proxies y colecciones perezosas para la mayoría de asociaciones a clases que probablemente no se encuentren en el caché de segundo nivel. Para las asociaciones a clases en caché, donde hay una probabilidad de acceso a caché extremadamente alta, deshabilite explícitamente la recuperación temprana usando lazy="false". Cuando la recuperación por unión sea apropiada para un caso de uso en particular, utilice una consulta con un left join fetch.

Use el patrón de sesión abierta en vista o una fase de ensamblado disciplinada para evitar problemas con datos no recuperados.

Hibernate libera al desarrollador de escribir tediosos objetos de transferencia de datos (DTO del inglés Data Transfer Objects). En una arquitectura tradicional de EJB, los DTOs tienen un propósito doble: primero, atacan el problema de que los beans de entidad no son serializables. Segundo, definen implícitamente una fase de ensamblado cuando se recuperan y se forman (marshalling) todos los datos a usar por la vista en los DTOs antes de devolver el control al nivel de presentación. Hibernate elimina el primer propósito. Sin embargo, aún necesita una fase de ensamblado a menos de que esté preparado para tener el contexto de persistencia (la sesión) abierto a través del proceso de entrega de la vista. Piense en sus métodos empresariales como si tuviesen un contrato estricto con el nivel de presentación sobre qué datos están disponibles en los objetos separados. Esta no es una limitación de Hibernate. Este es un requerimiento fundamental de acceso seguro a datos transaccionales.

Considere abstraer su lógica empresarial de Hibernate:

Oculte el código de acceso a datos de Hibernate detrás de una interfaz. Combine los patrones DAO y sesión local de hilo. Incluso puede hacer algunas clases persistentes por medio de JDBC escrito a mano, asociadas a Hibernate por medio de un UserType. Sin embargo, este consejo va para las aplicaciones "suficientemente grandes". No es apropiado para una aplicación con cinco tablas.

No utilice mapeos de asociación exóticos:

Son raros los casos de uso de asociaciones reales muchos-a-muchos. La mayor parte del tiempo necesita información adicional almacenada en una "tabla de enlace". En este caso, es mucho mejor usar dos asociaciones uno-a-muchos a una clase de enlace intermedio. De hecho, la mayoría de las asociaciones son uno-a-muchos y muchos-a-uno. Por esta razón, debe tener cuidado al utilizar cualquier otro estilo de asociación.

Prefiera las asociaciones bidireccionales:

Las asociaciones unidireccionales son más difíciles de consultar. En una aplicación grande, casi todas las asociaciones deben ser navegables en ambas direcciones en consultas.