hibernate-orm/reference/es/modules/best_practices.xml

230 lines
14 KiB
XML

<chapter id="best-practices" revision="3">
<title>Mejores Pr&#x00e1;cticas</title>
<variablelist spacing="compact">
<varlistentry>
<term>Escribe clase finamente granularizadas y mapealas usando <literal>&lt;component&gt;</literal>.</term>
<listitem>
<para>
Usa una clase <literal>Direcci&#x00f3;n</literal> para encapsular <literal>calle</literal>,
<literal>distrito</literal>, <literal>estado</literal>, <literal>c&#x00f3;digo postal</literal>.
Esto alienta la reutilizaci&#x00f3;n de c&#x00f3;digo y simplifica el refactoring.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Declara las propiedades identificadoras en clases persistentes.</term>
<listitem>
<para>
Hibernate hace opcionales las propiedades identificadoras. Existen todo tipo de razones
por las que debes usarlas. Recomendamos que los identificadores sean 'sint&#x00e9;ticos'
(generados, sin ning&#x00fa;n significado de negocio).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Identifica las claves naturales.</term>
<listitem>
<para>
Identifica las claves naturales de todas las entidades, y mapealas usando
<literal>&lt;natural-id&gt;</literal>. Implementa <literal>equals()</literal> y
<literal>hashCode()</literal> para comparar las propiedades que componen la clave natural.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Coloca cada mapeo de clase en su propio fichero.</term>
<listitem>
<para>
No uses un solo documento monol&#x00ed;tico de mapeo. Mapea <literal>com.eg.Foo</literal> en
el fichero <literal>com/eg/Foo.hbm.xml</literal>. Esto tiene sentido particularmente en un
ambiente de equipo.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Carga los mapeos como recursos.</term>
<listitem>
<para>
Despliega los mapeos junto a las clases que mapean.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Considera externalizar las cadenas de consulta.</term>
<listitem>
<para>
Esta es una buena pr&#x00e1;ctica si tus consultas llaman a funciones SQL que no son del
est&#x00e1;ndar ANSI. Externalizar las cadenas de consulta a ficheros de mapeo har&#x00e1; la
aplicaci&#x00f3;n m&#x00e1;s portable.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Usa variables de ligado.</term>
<listitem>
<para>
Igual que en JDBC, siempre remplaza valores no constantes con "?". &#x00a1;Nunca uses manipulaci&#x00f3;n
de cadenas para ligar un valor no constante en una consulta! Incluso mejor, considera usar
par&#x00e1;metros con nombre en las consultas.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>No manejes tus propias conexiones JDBC.</term>
<listitem>
<para>
Hibernate deja a la aplicaci&#x00f3;n administre las conexiones JDBC. Este enfoque debe considerarse
como &#x00fa;ltimo recurso. Si no puedes usar los provedores de conexi&#x00f3;n prefabricados, considera
prover tu propia implementaci&#x00f3;n de <literal>org.hibernate.connection.ConnectionProvider</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Considera usar un tipo personalizado.</term>
<listitem>
<para>
Sup&#x00f3;n que tienes un tipo Java, digamos de alguna biblioteca, que necesita hacerse persistente
pero no provee los m&#x00e9;todos de acceso necesarios para mapearlo como un componente. Debes considerar
implementar <literal>org.hibernate.UserType</literal>. Este enfoque libera al c&#x00f3;digo de aplicaci&#x00f3;n
de implementar transformaciones a / desde un tipo Hibernate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Usa JDBC codificado a mano en cuellos de botella.</term>
<listitem>
<para>
En &#x00e1;reas del sistema de rendimiento cr&#x00ed;tico, algunos tipos de operaciones podr&#x00ed;an beneficiarse
del JDBC directo. Pero por favor, espero hasta que <emphasis>sepas</emphasis> que algo es
un cuello de botella. Y no asumas que el JDBC directo es necesariamente m&#x00e1;s r&#x00e1;pido. Si necesitas
usar JDBC directo, podr&#x00ed;a ser valioso abrir una <literal>Session</literal> de Hibernate y usar esa
conexi&#x00f3;n JDBC. De esta forma puedes usar a&#x00fa;n la misma estrategia de transacci&#x00f3;n y el mismo
proveedor de conexiones subyacente.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Comprende la limpieza (flushing) de <literal>Session</literal>.</term>
<listitem>
<para>
De vez en cuando la sesi&#x00f3;n sincroniza su estado persistente con la base de datos. El rendimiento
se ver&#x00e1; afectado si este proceso ocurre demasiado frecuentemente. A veces puedes minimizar
limpieza innecesaria deshabilitando la limpieza autom&#x00e1;tica o incluso cambiando el orden de las
consultas u otras operaciones en una transacci&#x00f3;n en particular.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>En una aplicaci&#x00f3;n en tres gradas, considera usar objetos separados.</term>
<listitem>
<para>
Al usar una arquitectura de servlet / sesi&#x00f3;n, puedes pasar objetos persistentes en el bean de
sesi&#x00f3;n hacia y desde la capa de servlet / JSP. Usa una sesi&#x00f3;n nueva para atender el servicio de cada
petici&#x00f3;n. Usa <literal>Session.merge()</literal> o <literal>Session.saveOrUpdate()</literal> para
sincronizar los objetos con la base de datos.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>En una arquitectura en dos gradas, considera usar contexto de persistencia largos.</term>
<listitem>
<para>
Las transacciones de base de datos tienen que ser tan cortas como sea posible. Sin embargo,
frecuentemente es necesario implementar <emphasis>transacciones de aplicaci&#x00f3;n</emphasis>
ejecut&#x00e1;ndose en largo, una sola unidad de trabajo desde el punto de vista de un usuario.
Una transacci&#x00f3;n de aplicaci&#x00f3;n puede abarcar muchos ciclos petici&#x00f3;n/respuesta del cliente.
Es com&#x00fa;n usar objetos separados para implementar transacciones de aplicaci&#x00f3;n. Una alternativa,
extremadamente apropiada en arquitecturas en dos gradas, es mantener un solo contacto de persistencia
abierto (sesi&#x00f3;n) para todo el ciclo de vida de la transacci&#x00f3;n de aplicaci&#x00f3;n y simplemente
desconectar de la conexi&#x00f3;n JDBC al final de cada petici&#x00f3;n, y reconectar al comienzo de la
petici&#x00f3;n subsecuente. Nunca compartas una &#x00fa;nica sesi&#x00f3;n a trav&#x00e9;s de m&#x00e1;s de una transacci&#x00f3;n
de aplicaci&#x00f3;n, o estar&#x00e1;s trabajando con datos añejos.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>No trates la excepciones como recuperables.</term>
<listitem>
<para>
Esto es m&#x00e1;s una pr&#x00e1;ctica necesaria que una "mejor" pr&#x00e1;ctica. Cuando ocurra una excepci&#x00f3;n,
deshaz (rollback) la <literal>Transaction</literal> y cierra la <literal>Session</literal>.
Si no lo haces, Hibernate no puede garantizar que el estado en memoria representa con exactitud
el estado persistente. Como un caso especial de esto, no uses <literal>Session.load()</literal>
para determinar si una instancia con el identificador dado existe en la base de datos. En cambio,
usa <literal>Session.get()</literal> o una consulta.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Prefiere la recuperaci&#x00f3;n perezosa para las asociaciones.</term>
<listitem>
<para>
Usa escasamente la recuperaci&#x00f3;n temprana. Usa proxies y colecciones perezosas para la mayor&#x00ed;a
de asociaciones a clases probablemente no est&#x00e9;n mantenidas en el cach&#x00e9; de segundo nivel. Para
las asociaciones a clases en cach&#x00e9;, donde hay una probabilidad de acceso a cach&#x00e9; extremadamente
alta, deshabilita expl&#x00ed;citamente la recuperaci&#x00f3;n temprana usando <literal>lazy="false"</literal>.
Cuando sea apropiada la recuperaci&#x00f3;n por uni&#x00f3;n (join fetching) para un caso de uso en particular,
usa una consulta con un <literal>left join fetch</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Usa el patr&#x00f3;n <emphasis>sesi&#x00f3;n abierta en vista</emphasis>, o una <emphasis>fase de ensamblado</emphasis>
disciplinada para evitar problemas con datos no recuperados.
</term>
<listitem>
<para>
Hibernate liberal al desarrollador de escribir <emphasis>Objetos de Transferencia de Datos
(Data Transfer Objects)</emphasis> (DTO). En una arquitectura tradicional de EJB, los DTOs tienen
un prop&#x00f3;sito doble: primero, atacan el problema que los beans de entidad no son serializables.
Segundo, definen impl&#x00ed;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 a la grada de
presentaci&#x00f3;n. Hibernate elimina el primer prop&#x00f3;sito. Sin embargo, a&#x00fa;n necesitas una fase
de ensamblado (piensa en tus m&#x00e9;todos de negocio como si tuviesen un contrato estricto con la grada
de presentaci&#x00f3;n sobre qu&#x00e9; datos est&#x00e1;n disponibles en los objetos separados) a menos que est&#x00e9;s
preparado para tener el contexto de persistencia (la sesi&#x00f3;n) abierto a trav&#x00e9;s del proceso
de renderizaci&#x00f3;n de la vista. &#x00a1;Esta no es una limitaci&#x00f3;n de Hibernate! Es un requerimiento
fundamental de acceso seguro a datos transaccionales.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Considera abstraer tu l&#x00f3;gica de negocio de Hibernate</term>
<listitem>
<para>
Oculta el c&#x00f3;digo de acceso a datos (Hibernate) detr&#x00e1;s de una interface. Combina los patrones
<emphasis>DAO</emphasis> y <emphasis>Sesi&#x00f3;n de Hebra Local</emphasis>. Incluso puedes tener
algunas clases hechas persistentes por JDBC escrito a mano, asociadas a Hibernate por medio
de un <literal>UserType</literal>. (Este consejo est&#x00e1; pensado para aplicaciones "suficientemente
grandes"; &#x00a1;no es apropiado para una aplicaci&#x00f3;n con cinco tablas!)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>No uses mapeos de asociaci&#x00f3;n ex&#x00f3;ticos.</term>
<listitem>
<para>
Son raros los casos de uso de asociaciones reales muchos-a-muchos. La mayor parte del tiempo
necesitas informaci&#x00f3;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 intermedia. De hecho, pensamos
que la mayor&#x00ed;a de asociaciones son uno-a-muchos y muchos-a-uno, debes ser cuidadoso al usr
cualquier otro estilo de asociaci&#x00f3;n y preguntarte si es realmente necesario.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Prefiere las asociaciones bidireccionales.</term>
<listitem>
<para>
Las asociaciones unidireccionales son m&#x00e1;s dif&#x00ed;ciles de consultar. En una aplicaci&#x00f3;n grande,
casi todas las asociaciones deben ser navegables en ambas direcciones en consultas.
</para>
</listitem>
</varlistentry>
</variablelist>
</chapter>