mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-03-02 15:59:18 +00:00
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@7121 1b8cb986-b30d-0410-93ca-fae66ebed9b2
3223 lines
160 KiB
XML
3223 lines
160 KiB
XML
<chapter id="mapping">
|
|
<title>Mapeo O/R Básico</title>
|
|
|
|
<sect1 id="mapping-declaration" revision="1">
|
|
<title>Declaración de mapeo</title>
|
|
|
|
<para>
|
|
Los mapeos objeto/relacional se definen usualmente en un documento XML.
|
|
El documento de mapeo está diseñado para ser leíble y
|
|
editable a mano. El lenguaje de mapeo es Java-céntrico, o sea que los
|
|
mapeos se construyen alrededor de declaraciones de clases persistentes,
|
|
no declaraciones de tablas.
|
|
</para>
|
|
|
|
<para>
|
|
Observa que, incluso aunque muchos usuarios de Hibernate eligen escribir el
|
|
XML a mano, existe una cantidad de herramientas para generar el documento de
|
|
mapeo, incluyendo XDoclet, Middlegen y AndroMDA.
|
|
</para>
|
|
|
|
<para>
|
|
Comencemos por un mapeo de ejemplo:
|
|
</para>
|
|
|
|
<programlisting id="mapping-declaration-ex1" revision="1"><![CDATA[<?xml version="1.0"?>
|
|
<!DOCTYPE hibernate-mapping PUBLIC
|
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
|
|
|
<hibernate-mapping package="eg">
|
|
|
|
<class name="Cat"
|
|
table="cats"
|
|
discriminator-value="C">
|
|
|
|
<id name="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
|
|
<discriminator column="subclass"
|
|
type="character"/>
|
|
|
|
<property name="weight"/>
|
|
|
|
<property name="birthdate"
|
|
type="date"
|
|
not-null="true"
|
|
update="false"/>
|
|
|
|
<property name="color"
|
|
type="eg.types.ColorUserType"
|
|
not-null="true"
|
|
update="false"/>
|
|
|
|
<property name="sex"
|
|
not-null="true"
|
|
update="false"/>
|
|
|
|
<property name="litterId"
|
|
column="litterId"
|
|
update="false"/>
|
|
|
|
<many-to-one name="mother"
|
|
column="mother_id"
|
|
update="false"/>
|
|
|
|
<set name="kittens"
|
|
inverse="true"
|
|
order-by="litter_id">
|
|
<key column="mother_id"/>
|
|
<one-to-many class="Cat"/>
|
|
</set>
|
|
|
|
<subclass name="DomesticCat"
|
|
discriminator-value="D">
|
|
|
|
<property name="name"
|
|
type="string"/>
|
|
|
|
</subclass>
|
|
|
|
</class>
|
|
|
|
<class name="Dog">
|
|
<!-- mapping for Dog could go here -->
|
|
</class>
|
|
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
Discutiremos ahora el contenido del documento de mapeo. Describiremos sólo los
|
|
elementos y atributos que son usados por Hibernate en tiempo de ejecución. El
|
|
documento de mapeo contiene además algunos atributos y elementos extra opcionales
|
|
que afectan los esquemas de base de datos exportados por la herramienta de exportación
|
|
de esquemas. (Por ejemplo, el atributo <literal>not-null</literal>.)
|
|
</para>
|
|
|
|
|
|
|
|
<sect2 id="mapping-declaration-doctype" revision="2">
|
|
<title>Doctype</title>
|
|
|
|
<para>
|
|
Todos los mapeos XML deben declarar el doctype mostrado. El DTD actual puede
|
|
ser encontrado en el URL mencionado arriba, en el directorio
|
|
<literal>hibernate-x.x.x/src/org/hibernate</literal>, o en <literal>hibernate3.jar</literal>.
|
|
Hibernate siempre buscará el DTD primero en el classpath. Si experimentas
|
|
búsquedas del DTD usando una conexión de Internet, chequea tu declaración
|
|
de DTD contra la contenida en el classpath.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-mapping" revision="3">
|
|
<title>hibernate-mapping</title>
|
|
|
|
<para>
|
|
Este elemento tiene muchos atributos opcionales. Los atributos <literal>schema</literal>
|
|
y <literal>catalog</literal> especifican que las tablas a las que se refiere en el mapeo
|
|
pertenecen al esquema y/o catálogo mencionado(s). De especificarse, los nombres de
|
|
tablas serán cualificados por el nombre de esquema y catálogo dados.
|
|
De omitirse, los nombres de tablas no serán cualificados. El atributo
|
|
<literal>default-cascade</literal> especifica qué estilo de cascada debe asumirse
|
|
para las propiedades y colecciones que no especifican un atributo <literal>cascade</literal>.
|
|
El atributo <literal>auto-import</literal> nos permite usar nombres de clase sin cualificar
|
|
en el lenguaje de consulta, por defecto.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="hm1" coords="2 55"/>
|
|
<area id="hm2" coords="3 55"/>
|
|
<area id="hm3" coords="4 55"/>
|
|
<area id="hm4" coords="5 55"/>
|
|
<area id="hm5" coords="6 55"/>
|
|
<area id="hm6" coords="7 55"/>
|
|
<area id="hm7" coords="8 55"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<hibernate-mapping
|
|
schema="schemaName"
|
|
catalog="catalogName"
|
|
default-cascade="cascade_style"
|
|
default-access="field|property|ClassName"
|
|
default-lazy="true|false"
|
|
auto-import="true|false"
|
|
package="package.name"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="hm1">
|
|
<para>
|
|
<literal>schema</literal> (opcional): El nombre de un esquema de la base de datos.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm2">
|
|
<para>
|
|
<literal>catalog</literal> (opcional): El nombre de un catálogo de la base de datos.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm3">
|
|
<para>
|
|
<literal>default-cascade</literal> (opcional - por defecto a <literal>none</literal>):
|
|
Un estilo de cascada por defecto.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm4">
|
|
<para>
|
|
<literal>default-access</literal> (opcional - por defecto a <literal>property</literal>):
|
|
La estrategia que Hibernate debe usar para acceder a todas las propiedades.
|
|
Puede ser una implementación personalizada de <literal>PropertyAccessor</literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm5">
|
|
<para>
|
|
<literal>default-lazy</literal> (opcional - por defecto a <literal>true</literal>):
|
|
El valor por defecto para los atributos <literal>lazy</literal> de mapeos de clase
|
|
y colleción no especificados.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm6">
|
|
<para>
|
|
<literal>auto-import</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica si podemos usar nombres de clases no cualificados (de clases en este mapeo)
|
|
en el lenguaje de consulta.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="hm7">
|
|
<para>
|
|
<literal>package</literal> (opcional): Especifica un prefijo de paquete a asumir
|
|
para los nombres no cualificados de clase en el documento de mapeo.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Si tienes dos clases persistentes con el mismo nombre (sin cualificar), debes establecer
|
|
<literal>auto-import="false"</literal>. Hibernate lanzará una excepción si
|
|
intentas asignar dos clases al mismo nombre "importado".
|
|
</para>
|
|
|
|
<para>
|
|
Observa que el elemento <literal>hibernate-mapping</literal> te permite anidar
|
|
muchos mapeos <literal><class></literal> persistentes, como se muestra arriba.
|
|
Sin embargo, es una buena práctica (y se espera de algunas herramientas) mapear
|
|
sólo a una sola clase persistente (o a una sola jerarquía de clases) en
|
|
un fichero de mapeo y nombrarlo después de la superclase persistente;
|
|
por ejemplo, <literal>Cat.hbm.xml</literal>, <literal>Dog.hbm.xml</literal>,
|
|
o, si se usa herencia, <literal>Animal.hbm.xml</literal>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-class" revision="3">
|
|
<title>class</title>
|
|
|
|
<para>
|
|
Puedes declarar una clase persistente usando el elemento <literal>class</literal>:
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="class1" coords="2 55"/>
|
|
<area id="class2" coords="3 55" />
|
|
<area id="class3" coords="4 55"/>
|
|
<area id="class4" coords="5 55" />
|
|
<area id="class5" coords="6 55"/>
|
|
<area id="class6" coords="7 55" />
|
|
<area id="class7" coords="8 55"/>
|
|
<area id="class8" coords="9 55" />
|
|
<area id="class9" coords="10 55" />
|
|
<area id="class10" coords="11 55"/>
|
|
<area id="class11" coords="12 55"/>
|
|
<area id="class12" coords="13 55"/>
|
|
<area id="class13" coords="14 55"/>
|
|
<area id="class14" coords="15 55"/>
|
|
<area id="class15" coords="16 55"/>
|
|
<area id="class16" coords="17 55"/>
|
|
<area id="class17" coords="18 55"/>
|
|
<area id="class18" coords="19 55"/>
|
|
<area id="class19" coords="20 55"/>
|
|
<area id="class20" coords="21 55"/>
|
|
<area id="class21" coords="22 55"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<class
|
|
name="ClassName"
|
|
table="tableName"
|
|
discriminator-value="discriminator_value"
|
|
mutable="true|false"
|
|
schema="owner"
|
|
catalog="catalog"
|
|
proxy="ProxyInterface"
|
|
dynamic-update="true|false"
|
|
dynamic-insert="true|false"
|
|
select-before-update="true|false"
|
|
polymorphism="implicit|explicit"
|
|
where="arbitrary sql where condition"
|
|
persister="PersisterClass"
|
|
batch-size="N"
|
|
optimistic-lock="none|version|dirty|all"
|
|
lazy="true|false"
|
|
entity-name="EntityName"
|
|
check="arbitrary sql check condition"
|
|
rowid="rowid"
|
|
subselect="SQL expression"
|
|
abstract="true|false"
|
|
node="element-name"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="class1">
|
|
<para>
|
|
<literal>name</literal> (opcional): El nombre completamente cualificado de la clase
|
|
Java persistente (o interface). Si este atributo es omitido, se asume que el mapeo
|
|
es para una entidad non-POJO.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class2">
|
|
<para>
|
|
<literal>table</literal> (opcional - por defecto al nombre no cualificado de la clase):
|
|
El nombre de su tabla en base de datos.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class3">
|
|
<para>
|
|
<literal>discriminator-value</literal> (opcional - por defecto al nombre de la clase):
|
|
Un valor que distingue subclases individuales, usado para el comportamiento
|
|
polimórfico. Los valores aceptables incluyen <literal>null</literal>
|
|
y <literal>not null</literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class4">
|
|
<para>
|
|
<literal>mutable</literal> (opcional, por defecto a <literal>true</literal>):
|
|
Especifica que las instancias de la clase (no) son mutables.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class5">
|
|
<para>
|
|
<literal>schema</literal> (opcional): Sobreescribe el nombre de esquema especificado
|
|
por el elemento raíz <literal><hibernate-mapping></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class6">
|
|
<para>
|
|
<literal>catalog</literal> (opcional): Sobreescribe el nombre de catálogo
|
|
especificado por el elemento raíz <literal><hibernate-mapping></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class7">
|
|
<para>
|
|
<literal>proxy</literal> (opcional): Especifica una interface a usar para proxies
|
|
de inicialización perezosa. Puedes especificar el nombre mismo de la clase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class8">
|
|
<para>
|
|
<literal>dynamic-update</literal> (opcional, por defecto a <literal>false</literal>):
|
|
Especifica que el SQL <literal>UPDATE</literal> debe ser generado en tiempo de
|
|
ejecución y contener solamente aquellas columnas cuyo valor haya cambiado.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class9">
|
|
<para>
|
|
<literal>dynamic-insert</literal> (opcional, por defecto a <literal>false</literal>):
|
|
Especifica que el SQL <literal>INSERT</literal> debe ser generado en tiempo de
|
|
ejecución y contener solamente aquellas columnas cuyo valores no son nulos.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class10">
|
|
<para>
|
|
<literal>select-before-update</literal> (opcional, por defecto a <literal>false</literal>):
|
|
Especifica que Hibernate <emphasis>nunca</emphasis> debe realizar un SQL <literal>UPDATE</literal>
|
|
a menos que se tenga certeza que un objeto haya sido modificado realmente.
|
|
En ciertos casos, (realmente, sólo cuando un objeto transitorio ha sido asociado
|
|
con una sesión nueva usando <literal>update()</literal>), esto significa que Hibernate
|
|
realizará una SQL <literal>SELECT</literal> extra para determinar si un
|
|
<literal>UPDATE</literal> es realmente requerido.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class11">
|
|
<para>
|
|
<literal>polymorphism</literal> (opcional, por defecto a <literal>implicit</literal>):
|
|
Determina si se usa polimorfismo de consulta implícito o explícito.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class12">
|
|
<para>
|
|
<literal>where</literal> (opcional) especifica una condición SQL <literal>WHERE</literal>
|
|
arbitraria paraa ser usada al recuperar objetos de esta clase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class13">
|
|
<para>
|
|
<literal>persister</literal> (opcional): Especifica un <literal>ClassPersister</literal>
|
|
personalizado.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class14">
|
|
<para>
|
|
<literal>batch-size</literal> (opcional, por defecto a <literal>1</literal>)
|
|
especifica un "tamaño de lote" para traer instancias de esta clase por
|
|
identificador.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class15">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional, por defecto a <literal>version</literal>):
|
|
Determina la estrategia optimista de bloqueo.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class16">
|
|
<para>
|
|
<literal>lazy</literal> (opcional):
|
|
La recuperación perezosa puede ser deshabilitada por completo estableciendo
|
|
<literal>lazy="false"</literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class17">
|
|
<para>
|
|
<literal>entity-name</literal> (opcional): Hibernate3 permite que una clase sea
|
|
mapeada varias veces (potencialmente a tablas diferentes), y permite que los mapeos
|
|
de entidad sean representados por Maps o XML al nivel de Java. En estos casos,
|
|
debes proveer un nombre explícito arbitrario para la entidad.
|
|
Para más información, mira
|
|
<xref linkend="persistent-classes-dynamicmodels"/> y <xref linkend="xml"/>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class18">
|
|
<para>
|
|
<literal>check</literal> (opcional): Una expresión SQL usada para generar
|
|
una restricción <emphasis>check</emphasis> multi-fila para la generación
|
|
automática de esquema.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class19">
|
|
<para>
|
|
<literal>rowid</literal> (opcional): Hibernate puede usar los llamados ROWIDs en las
|
|
bases de datos que los soporten. Por ejemplo, en Oracle, Hibernate puede usar la columna
|
|
extra <literal>rowid</literal> para actualizaciones rápidas si estableces esta
|
|
opción a <literal>rowid</literal>. Un ROWID es un detalle de implementación
|
|
y representa la posición física de la tupla almacenada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class20">
|
|
<para>
|
|
<literal>subselect</literal> (opcional): Mapea una entidad inmutable y de sólo
|
|
lectura a una subselect de base de datos. Es útil si quieres tener una vista
|
|
en vez de una tabla base, pero no tienes vistas. Mira debajo para más información.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="class21">
|
|
<para>
|
|
<literal>abstract</literal> (opcional): Usado para marcar superclases abstractas en
|
|
jerarquías <literal><union-subclass></literal>.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Es perfectamente aceptable que la clase persistente mencionada sea una interface.
|
|
Entonces declararías clases que implementan esa interface usando el elemento
|
|
<literal><subclass></literal>. Puedes persistir cualquier clase interna
|
|
<emphasis>estática</emphasis>. Debes especificar el nombre de la clase usando la forma
|
|
estándar. Por ejemplo, <literal>eg.Foo$Bar</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Las clases inmutables, <literal>mutable="false"</literal>, no pueden ser actualizadas o
|
|
borradas por la aplicación. Esto permite a Hibernate hacer ciertas optimizaciones
|
|
menores de rendimiento.
|
|
</para>
|
|
|
|
<para>
|
|
El atributo opcional <literal>proxy</literal> habilita la inicialización postergada
|
|
de instancias persistentes de la clase. Hibernate inicialmente retornará proxies
|
|
CGLIB que implementan la interface mencionada. El objeto persistente real será
|
|
cargado cuando se invoque un método del proxy. Mira "Proxies para Inicialización
|
|
Postergada" debajo.
|
|
</para>
|
|
|
|
<para>
|
|
Por polimorfismo <emphasis>implícito</emphasis> se entiende que las instancias de la clase
|
|
serán devueltas por una consulta que mencione cualquier superclase, o interface implementada,
|
|
o la clase misma; y que las instancias de cualquier subclase de la clase serán devueltas
|
|
por una clase que mencione a la clase en sí.
|
|
Por polimorfismo <emphasis>explícito</emphasis> se entiende que instancias de la clase
|
|
serán devueltas sólo por consultas que mencionen explícitamente la clase;
|
|
y que las consultas que mencionen la clase devolverán sólo instancias de subclases
|
|
mapeadas dentro de esta declaración <literal><class></literal> como una
|
|
<literal><subclass></literal> o <literal><joined-subclass></literal>.
|
|
Para la mayoría de los propósitos el defecto,
|
|
<literal>polymorphism="implicit"</literal>, resulta apropiado.
|
|
El polimorfismo explícito es útil cuando dos clases diferentes están
|
|
mapeadas a la misma tabla (esto permite tener una clase "liviana" que contenga un subconjunto
|
|
de columnas de la tabla).
|
|
</para>
|
|
|
|
<para>
|
|
El atributo <literal>persister</literal> te permite personalizar la estrategia de persistencia
|
|
para la clase. Puedes, por ejemplo, especificar tu propia subclase de
|
|
<literal>org.hibernate.persister.EntityPersister</literal> o incluso puedes proveer una implementación
|
|
completamente nueva de la interface <literal>org.hibernate.persister.ClassPersister</literal> que implemente
|
|
la persistencia por medio, por ejemplo, de llamadas a procedimientos almacenados, serialización a
|
|
ficheros planos o LDAP. Para un ejemplo simple (de persistencia a una <literal>Hashtable</literal>) mira
|
|
<literal>org.hibernate.test.CustomPersister</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Observa que los valores de <literal>dynamic-update</literal> y <literal>dynamic-insert</literal>
|
|
no son heredados por las subclases y por lo tanto deben especificarse en los elementos
|
|
<literal><subclass></literal> o <literal><joined-subclass></literal>.
|
|
Estos ajustes pueden incrementar el rendimiento en algunos casos, pero podrían mermarlo en otros.
|
|
Ten juicio en su uso.
|
|
</para>
|
|
|
|
<para>
|
|
Generalmente el uso de <literal>select-before-update</literal> disminuirá el rendimiento.
|
|
Es muy útil prevenir que se llame innecesariamente a un disparador de actualización de
|
|
base de datos al volver a unir un grafo de instancias separadas a una <literal>Session</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Si habilitas <literal>dynamic-update</literal>, tendrás opción de estrategias
|
|
de bloqueo optimistas:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>version</literal> chequea las columnas de versión/timestamp
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>all</literal> chequea todas las columnas
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>dirty</literal> chequea las columnas modificadas, permitiendo algunas
|
|
actualizaciones concurrentes
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>none</literal> no usa bloqueo optimista
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
Recomendamos <emphasis>muy</emphasis> fuertemente que uses columnas de
|
|
versión/timestamp para bloqueo optimista con Hibernate. Esta es la estrategia
|
|
óptima con respecto al rendimiento y es la única estrategia que maneja
|
|
correctamente las modificaciones hechas a las instancias separadas.
|
|
(por ejemplo, cuando se usa <literal>Session.merge()</literal>).
|
|
</para>
|
|
|
|
<para>
|
|
Para un mapeo de Hibernate, no hay diferencia entre una vista y una tabla base.
|
|
Como se supone esto es transparente a nivel de base de datos (observa que algunos
|
|
DBMS no soportan correctamente las vistas, especialmente con las actualizaciones).
|
|
A veces quieres usar una vista, pero no puedes crear una en la base de datos
|
|
(por ejemplo, con un esquema heredado). En este caso, puedes mapear una entidad inmutable
|
|
de sólo lectura a una expresión de subconsulta SQL dada.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Summary">
|
|
<subselect>
|
|
select item.name, max(bid.amount), count(*)
|
|
from item
|
|
join bid on bid.item_id = item.id
|
|
group by item.name
|
|
</subselect>
|
|
<synchronize table="item"/>
|
|
<synchronize table="bid"/>
|
|
<id name="name"/>
|
|
...
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
Declara las tablas con las que sincronizar esta entidad, asegurando que el auto-flush
|
|
ocurre correctamente, y que las consultas contra la entidad derivada no devuelven datos
|
|
desactualizados. El <literal><subselect></literal> está disponible tanto
|
|
como un atributo o como un elemento anidado de mapeo.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-id" revision="3">
|
|
<title>id</title>
|
|
|
|
<para>
|
|
Las clases mapeadas <emphasis>deben</emphasis> declarar la columna de clave primaria de la tabla
|
|
de la base de datos. En la mayoría de los casos tendrá también una propiedad
|
|
estilo Javabeans que tenga el identificador único de una instancia. El elemento
|
|
<literal><id></literal> define el mapeo de esa propiedad a la columna de clave primaria.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="id1" coords="2 70"/>
|
|
<area id="id2" coords="3 70" />
|
|
<area id="id3" coords="4 70"/>
|
|
<area id="id4" coords="5 70" />
|
|
<area id="id5" coords="6 70" />
|
|
</areaspec>
|
|
<programlisting><![CDATA[<id
|
|
name="propertyName"
|
|
type="typename"
|
|
column="column_name"
|
|
unsaved-value="null|any|none|undefined|id_value"
|
|
access="field|property|ClassName"
|
|
node="element-name|@attribute-name|element/@attribute|.">
|
|
|
|
<generator class="generatorClass"/>
|
|
</id>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="id1">
|
|
<para>
|
|
<literal>name</literal> (opcional): El nombre de la propiedad del indentificador.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="id2">
|
|
<para>
|
|
<literal>type</literal> (opcional): Un nombre que indica el tipo Hibernate.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="id3">
|
|
<para>
|
|
<literal>column</literal> (opcional - por defecto al nombre de la propiedad):
|
|
El nombre de la columna de clave primaria.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="id4">
|
|
<para>
|
|
<literal>unsaved-value</literal> (opcional - por defecto al valor "sensible"):
|
|
Una valor de la propiedad identificadora que indica que una instancia está
|
|
recién instanciada (sin salvar), distinguiéndola de instancias separadas
|
|
que fueran salvadas o cargadas en una sesión previa.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="id5">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>):
|
|
La estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Si se omite el atributo <literal>name</literal>, se asume que la clase no tiene propiedad
|
|
identificadora.
|
|
</para>
|
|
|
|
<para>
|
|
El atributo <literal>unsaved-value</literal> es importante! Si la propiedad identificadora de tu
|
|
clase no tiene por defecto el valor por defecto normal de Java (null o cero), entonces debes especificar
|
|
el valor por defecto real.
|
|
</para>
|
|
|
|
<para>
|
|
Hay una declaración <literal><composite-id></literal> alternativa para permitir acceso
|
|
a datos heredados con claves compuestas. Desalentamos fuertemente su uso para cualquier otra cosa.
|
|
</para>
|
|
|
|
<sect3 id="mapping-declaration-id-generator" revision="2">
|
|
<title>Generator</title>
|
|
|
|
<para>
|
|
El elemento hijo opcional <literal><generator></literal> nombra una clase Java
|
|
usada en generar identificadores únicos para instancias de la clase persistente.
|
|
De requerirse algún parámetro para configurar o inicializar la instancia del generador,
|
|
se pasa usando el elemento <literal><param></literal>.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
|
|
<generator class="org.hibernate.id.TableHiLoGenerator">
|
|
<param name="table">uid_table</param>
|
|
<param name="column">next_hi_value_column</param>
|
|
</generator>
|
|
</id>]]></programlisting>
|
|
|
|
<para>
|
|
Todos los generadores implementan la interface <literal>org.hibernate.id.IdentifierGenerator</literal>.
|
|
Esta es una interface muy simple; algunas aplicaciones pueden escoger proveer sus propias
|
|
implementaciones especializadas. Sin embargo, Hibernate provee un rango de implementaciones
|
|
prefabricadas. Hay nombres alias de atajo para los generadores prefabricados:
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>increment</literal></term>
|
|
<listitem>
|
|
<para>
|
|
genera indentificadores de tipo <literal>long</literal>, <literal>short</literal> o
|
|
<literal>int</literal> que sólo son únicos cuando ningún otro proceso
|
|
está insertando datos en la misma tabla. <emphasis>No usar en un cluster.</emphasis>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>identity</literal></term>
|
|
<listitem>
|
|
<para>
|
|
soporta columnas de identidad en DB2, MySQL, MS SQL Server, Sybase y
|
|
HypersonicSQL. El identificador devuelto es de tipo <literal>long</literal>,
|
|
<literal>short</literal> o <literal>int</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>sequence</literal></term>
|
|
<listitem>
|
|
<para>
|
|
usa una secuencia en DB2, PostgreSQL, Oracle, SAP DB, McKoi o un generador
|
|
en Interbase. El identificador devuelto es de tipo <literal>long</literal>,
|
|
<literal>short</literal> o <literal>int</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>hilo</literal></term>
|
|
<listitem>
|
|
<para id="mapping-declaration-id-hilodescription" revision="1">
|
|
usa un algoritmo alto/bajo para generar eficientemente identificadores de tipo
|
|
<literal>long</literal>, <literal>short</literal> o <literal>int</literal>,
|
|
dada una tabla y columna como fuente de valores altos (por defecto
|
|
<literal>hibernate_unique_key</literal> y <literal>next_hi</literal> respectivamente).
|
|
El algoritmo alto/bajo genera identificadores que son únicos sólo para una
|
|
base de datos particular.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>seqhilo</literal></term>
|
|
<listitem>
|
|
<para>
|
|
usa un algoritmo alto/bajo para generar eficientemente identificadores de tipo
|
|
<literal>long</literal>, <literal>short</literal> o <literal>int</literal>,
|
|
dada una secuencia de base de datos.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>uuid</literal></term>
|
|
<listitem>
|
|
<para>
|
|
usa un algoritmo UUID de 128 bits para generar identificadore de tipo
|
|
cadena, únicos en una ref (se usa la direccón IP). El UUID
|
|
se codifica como una cadena hexadecimal de 32 dígitos de largo.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>guid</literal></term>
|
|
<listitem>
|
|
<para>
|
|
usa una cadena GUID generada por base de datos en MS SQL Server y MySQL.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>native</literal></term>
|
|
<listitem>
|
|
<para>
|
|
selecciona <literal>identity</literal>, <literal>sequence</literal> o
|
|
<literal>hilo</literal> dependiendo de las capacidades de la base de datos
|
|
subyacente.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>assigned</literal></term>
|
|
<listitem>
|
|
<para>
|
|
deja a la aplicación asignar un identificador al objeto antes
|
|
de que se llame a <literal>save()</literal>. Esta es la estrategia
|
|
por defecto si no se especifica un elemento <literal><generator></literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>select</literal></term>
|
|
<listitem>
|
|
<para>
|
|
recupera una clave primaria asignada por un disparador de base de datos
|
|
seleccionando la fila por alguna clave única y recuperando el valor de
|
|
la clave primaria.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>foreign</literal></term>
|
|
<listitem>
|
|
<para>
|
|
usa el identificador de otro objeto asociado. Generalmente usado en conjuncón
|
|
a una asociacón de clave primaria <literal><uno-a-uno></literal>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="mapping-declaration-id-hilo" revision="1">
|
|
<title>Algoritmo alto/bajo</title>
|
|
<para>
|
|
Los generadores <literal>hilo</literal> y <literal>seqhilo</literal> proveen dos implementaciones
|
|
alternativas del algoritmo alto/bajo, un enfoque favorito en generación de identificadores.
|
|
La primera implementación requiere de una tabla "especial" de base de datos para tener el siguiente
|
|
valor "alto" disponible.
|
|
La segunda usa una secuencia del estilo de Oracle (donde se soporte).
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
|
|
<generator class="hilo">
|
|
<param name="table">hi_value</param>
|
|
<param name="column">next_value</param>
|
|
<param name="max_lo">100</param>
|
|
</generator>
|
|
</id>]]></programlisting>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="cat_id">
|
|
<generator class="seqhilo">
|
|
<param name="sequence">hi_value</param>
|
|
<param name="max_lo">100</param>
|
|
</generator>
|
|
</id>]]></programlisting>
|
|
|
|
<para>
|
|
Desafortunadamente, no puedes usar <literal>hilo</literal> cuando le proveas tu propia
|
|
<literal>Connection</literal> a Hibernate. Cuando Hibernate está usando un datasource
|
|
del servidor de aplicaciones para obtener conexiones alistadas con JTA, debes configurar
|
|
correctamente el <literal>hibernate.transaction.manager_lookup_class</literal>.
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="mapping-declaration-id-uuid">
|
|
<title>Algoritmo UUID</title>
|
|
<para>
|
|
El UUID contiene: la dirección IP, el instante de arranque de la JVM
|
|
(con una precisión de un cuarto de segundo), el tiempo de sistema y un valor
|
|
de contador (único en la JVM). No es posible obtener una dirección MAC o
|
|
una dirección de memoria desde código Java, así que esto es lo mejor
|
|
que podemos hacer sin usar JNI.
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="mapping-declaration-id-sequences">
|
|
<title>Columnas de identidad y secuencias</title>
|
|
<para>
|
|
Para las bases de datos que soportan columnas de identidad (DB2, MySQL, Sybase, MS SQL),
|
|
puedes usar generación de claves <literal>identity</literal>. Para las bases de datos
|
|
que soportan secuencias (DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB) puedes usar la generación
|
|
de claves del estilo <literal>sequence</literal>. Ambas estrategias requieren dos consultas SQL
|
|
para insertar un nuevo objeto.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="person_id">
|
|
<generator class="sequence">
|
|
<param name="sequence">person_id_sequence</param>
|
|
</generator>
|
|
</id>]]></programlisting>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="person_id" unsaved-value="0">
|
|
<generator class="identity"/>
|
|
</id>]]></programlisting>
|
|
|
|
<para>
|
|
Para desarrollos multiplataforma, la estrategia <literal>native</literal>
|
|
eiligirá de entre las estrategias <literal>identity</literal>,
|
|
<literal>sequence</literal> y <literal>hilo</literal>, dependiendo de las capacidades
|
|
de la base de datos subyacentes.
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="mapping-declaration-id-assigned">
|
|
<title>Identificadores asignados</title>
|
|
<para>
|
|
Si quieres que la aplicación asigne los identificadores (en contraposición
|
|
a que los genere Hibernate), puedes usar el generador <literal>assigned</literal>.
|
|
Este generador especial usará el valor identificador ya asignado a la
|
|
propiedad identificadora del objeto. Este generador se usa cuandola clave primaria es
|
|
una clave natural en vez de una clave sustituta. Este es el comportamiento por defecto si
|
|
no especificas un elemento <literal><generator></literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Elegir el generador <literal>assigned</literal> hace que Hibernate use
|
|
<literal>unsaved-value="undefined"</literal>, forzando a Hibernate a ir
|
|
a la base de datos para determinar si una instancia es transitoria o separada,
|
|
a menos que haya una propiedad de versión o timestamp, o que tu definas
|
|
<literal>Interceptor.isUnsaved()</literal>.
|
|
</para>
|
|
</sect3>
|
|
|
|
<sect3 id="mapping-declaration-id-select">
|
|
<title>Claves primarias asignadas por disparadores</title>
|
|
<para>
|
|
Para esquemas heredados solamente (Hibernate no genera DDL con disparadores).
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<id name="id" type="long" column="person_id">
|
|
<generator class="select">
|
|
<param name="key">socialSecurityNumber</param>
|
|
</generator>
|
|
</id>]]></programlisting>
|
|
|
|
<para>
|
|
En el ejemplo de arriba, hay una propiedad ánica llamada
|
|
<literal>socialSecurityNumber</literal> definida por la clase, como
|
|
una clave natural, y una clave sustituta llamada <literal>person_id</literal>
|
|
cuyo valor es generado por un disparador.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-compositeid" revision="2">
|
|
<title>composite-id</title>
|
|
|
|
<programlisting><![CDATA[<composite-id
|
|
name="propertyName"
|
|
class="ClassName"
|
|
unsaved-value="undefined|any|none"
|
|
access="field|property|ClassName"
|
|
node="element-name|.">
|
|
|
|
<key-property name="propertyName" type="typename" column="column_name"/>
|
|
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
|
|
......
|
|
</composite-id>]]></programlisting>
|
|
|
|
<para>
|
|
Para una tabla con clave compuesta, puedes mapear múltiples propiedades
|
|
de la clase como propiedades identificadoras. El elemento <literal><composite-id></literal>
|
|
acepta los mapeos de propiedad <literal><key-property></literal> y
|
|
los mapeos <literal><key-many-to-one></literal> como elementos hijo.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<composite-id>
|
|
<key-property name="medicareNumber"/>
|
|
<key-property name="dependent"/>
|
|
</composite-id>]]></programlisting>
|
|
|
|
<para>
|
|
Tu clase persistente <emphasis>debe</emphasis> sobreescribir <literal>equals()</literal>
|
|
y <literal>hashCode()</literal> para implementar igualdad de identificador compuesto.
|
|
Debe también implementar <literal>Serializable</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Desafortunadamente, este enfoque de identificadores compuestos significa que un objeto
|
|
persistente es su propio identificador. No existe otra "asa" conveniente más que el
|
|
objeto mismo. Debes instanciar una instancia de la clase misma y poblar sus propiedades
|
|
identificadoras antes que puedas <literal>load()</literal> el estado persistente asociado
|
|
a una clave compuesta. Describiremos un enfoque mucho más conveniente donde el identificador
|
|
compuesto está implementado como una clase separada en <xref linkend="components-compositeid"/>.
|
|
Los atributos descriptos debajo solamente se aplican a este enfoque alternativo:
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para>
|
|
<literal>name</literal> (opcional): Una propiedad de tipo componente que tiene el identificador
|
|
compuesto (ver siguiente sección).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>class</literal> (opcional - por defecto al tipo de la propiedad determinado
|
|
por reflección): La clase del componente usado como identificador compuesto (ver siguiente sección).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>unsaved-value</literal> (opcional - por defecto a <literal>undefined</literal>):
|
|
Indica que las instancias transitorias deben ser consideradas como recién instanciadas,
|
|
si se establece a <literal>any</literal>, o separadas, si se establece a <literal>none</literal>.
|
|
Lo mejor
|
|
|
|
Indicates that transient instances should be considered newly instantiated, if set
|
|
to <literal>any</literal>, or detached, if set to <literal>none</literal>.
|
|
Lo mejor en todos los casos es dejar el valor por defecto.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-discriminator" revision="3">
|
|
<title>discriminator</title>
|
|
|
|
<para>
|
|
El elemento <literal><discriminator></literal> es requerido para la persistencia
|
|
polimórfica usando la estrategia de mapeo de tabla-por-jerarquía-de-clases y
|
|
declara una columna discriminadora de la tabla. La columna discriminidora contiene valores
|
|
de marca que le dicen a la capa de persistencia qué subclase instanciar para una fila
|
|
en particular. Un conjunto restringido de tipos puede ser usado:
|
|
<literal>string</literal>, <literal>character</literal>, <literal>integer</literal>,
|
|
<literal>byte</literal>, <literal>short</literal>, <literal>boolean</literal>,
|
|
<literal>yes_no</literal>, <literal>true_false</literal>.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="discriminator1" coords="2 60"/>
|
|
<area id="discriminator2" coords="3 60" />
|
|
<area id="discriminator3" coords="4 60" />
|
|
<area id="discriminator4" coords="5 60" />
|
|
<area id="discriminator5" coords="6 60" />
|
|
</areaspec>
|
|
<programlisting><![CDATA[<discriminator
|
|
column="discriminator_column"
|
|
type="discriminator_type"
|
|
force="true|false"
|
|
insert="true|false"
|
|
formula="arbitrary sql expression"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="discriminator1">
|
|
<para>
|
|
<literal>column</literal> (opcional - por defecto a <literal>class</literal>) el
|
|
nombre de la columna discriminadora.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="discriminator2">
|
|
<para>
|
|
<literal>type</literal> (opcional - por defecto a <literal>string</literal>) un
|
|
nombre que indique el tipo Hibernate
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="discriminator3">
|
|
<para>
|
|
<literal>force</literal> (optconal - por defecto a <literal>false</literal>)
|
|
"fuerza" a Hibernate a especificar valores discriminadores permitidos incluso
|
|
cuando se recuperan todas las instancias de la clase raíz.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="discriminator4">
|
|
<para>
|
|
<literal>insert</literal> (opcional - por defecto a <literal>true</literal>)
|
|
establezca este a <literal>false</literal> si tu columna discriminadora es
|
|
también parte de un identificador mapeado compuesto. (Le dice a Hibernate
|
|
que no incluya la columna en los SQL <literal>INSERT</literal>s.)
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="discriminator5">
|
|
<para>
|
|
<literal>formula</literal> (opcional) una expresión SQL arbitraria que
|
|
es ejecutada cuando un tipo tenga que ser evaluado. Permite dicriminación
|
|
basada en el contenido.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Los valores reales de la columna discriminadora están especificados por
|
|
el atributo <literal>discriminator-value</literal> de los elementos
|
|
<literal><class></literal> y <literal><subclass></literal>.
|
|
</para>
|
|
|
|
<para>
|
|
El atributo <literal>force</literal> es (sólo) útil si la tabla contiene
|
|
filas con valores discriminadores "extra" que no están mapeados a la clase
|
|
persistente. Generalmente este no es el caso.
|
|
</para>
|
|
|
|
<para>
|
|
Usando el atributo <literal>formula</literal> puedes declarar una expresión SQL
|
|
arbitraria que será usada para evaluar el tipo de una fila:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<discriminator
|
|
formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
|
|
type="integer"/>]]></programlisting>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-version" revision="1">
|
|
<title>version (opcional)</title>
|
|
|
|
<para>
|
|
El elemento <literal><version></literal> es opcional e indica que la
|
|
tabla contiene datos versionados. Esto es particularmente útil si planeas
|
|
usar <emphasis>transacciones largas</emphasis> (ver debajo).
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="version1" coords="2 70"/>
|
|
<area id="version2" coords="3 70"/>
|
|
<area id="version3" coords="4 70"/>
|
|
<area id="version4" coords="5 70"/>
|
|
<area id="version5" coords="6 70"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<version
|
|
column="version_column"
|
|
name="propertyName"
|
|
type="typename"
|
|
access="field|property|ClassName"
|
|
unsaved-value="null|negative|undefined"
|
|
node="element-name|@attribute-name|element/@attribute|."
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="version1">
|
|
<para>
|
|
<literal>column</literal> (opcional - por defecto al nombre de la propiedad): El nombre
|
|
de la columna que tiene el número de versión.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="version2">
|
|
<para>
|
|
<literal>name</literal>: El nombre de una propiedad de la clase persistente.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="version3">
|
|
<para>
|
|
<literal>type</literal> (opcional - por defecto a <literal>integer</literal>):
|
|
El tipo del nú.mero de vesión.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="version4">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="version5">
|
|
<para>
|
|
<literal>unsaved-value</literal> (opcional - por defecto a <literal>undefined</literal>):
|
|
Un valor de la propiedad de versión que indica que una instancia está
|
|
recién instanciada (sin guardar), distinguiéndola de instancias
|
|
separadas que fueran guardadas o cargadas en una sesión previa.
|
|
(<literal>undefined</literal> especifica que debe usarse el valor de la
|
|
propiedad identificadora.)
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Los números de versión deben ser de tipo <literal>long</literal>,
|
|
<literal>integer</literal>, <literal>short</literal>, <literal>timestamp</literal> o
|
|
<literal>calendar</literal> de Hibernate.
|
|
</para>
|
|
|
|
<para>
|
|
Una propiedad de versión o timestamp nunca debe ser nula para una instancia
|
|
separada, de modo que Hibernate detectará cualquier instancia con una versión
|
|
o timestamp nulo como transitoria, sin importar qué otras estrategias
|
|
<literal>unsaved-value</literal> se hayan especificado.
|
|
<emphasis>Declarar una propiedad de versón o timestamp nulable es una forma
|
|
fácil de evitar cualquier problema con la re-unión transitiva en Hibernate,
|
|
especialmente útil para que usa identificadores asignados o claves compuestas!</emphasis>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-timestamp">
|
|
<title>timestamp (opcional)</title>
|
|
|
|
<para>
|
|
El elemento opcional <literal><timestamp></literal> indica que la tabla contiene
|
|
datos con sellos de tiempo. Esto esta concebido como una alternativa al versionado.
|
|
Los timestamps (sellos de tiempo) son por su naturaleza una implementación menos
|
|
segura de bloqueo optimista. Sin embrago, a veces la aplicación puede usar los
|
|
timestamps en otras formas.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="timestamp1" coords="2 70"/>
|
|
<area id="timestamp2" coords="3 70" />
|
|
<area id="timestamp3" coords="4 70" />
|
|
<area id="timestamp4" coords="5 70" />
|
|
</areaspec>
|
|
<programlisting><![CDATA[<timestamp
|
|
column="timestamp_column"
|
|
name="propertyName"
|
|
access="field|property|ClassName"
|
|
unsaved-value="null|undefined"
|
|
node="element-name|@attribute-name|element/@attribute|."
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="timestamp1">
|
|
<para>
|
|
<literal>column</literal> (opcional - por defecto al nombre de la propiedad): El nombre
|
|
de una columna que tiene el timestamp.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="timestamp2">
|
|
<para>
|
|
<literal>name</literal>: El nombre de una propiedad del estilo JavaBeans de tipo
|
|
Java <literal>Date</literal> o <literal>Timestamp</literal> de la clase persistente.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="timestamp3">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="timestamp4">
|
|
<para>
|
|
<literal>unsaved-value</literal> (opcional - por defecto a <literal>null</literal>):
|
|
Un valor de propiedad de versión que indica que una instancia está
|
|
recién instanciada (sin guardar), distinguiéndola de instancias separadas
|
|
que hayan sido guardadas o cargadas en una sesión previa.
|
|
(<literal>undefined</literal> especifica que debe usarse el valor de la propiedad
|
|
identificadora.)
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Note that <literal><timestamp></literal> is equivalent to
|
|
<literal><version type="timestamp"></literal>.
|
|
</para>
|
|
</sect2>
|
|
|
|
|
|
<sect2 id="mapping-declaration-property" revision="2">
|
|
<title>property</title>
|
|
|
|
<para>
|
|
El elemento <literal><property></literal> declara una propiedad persistente estilo
|
|
JavaBean de la clase.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="property1" coords="2 70"/>
|
|
<area id="property2" coords="3 70"/>
|
|
<area id="property3" coords="4 70"/>
|
|
<areaset id="property4-5" coords="">
|
|
<area id="property4" coords='5 70'/>
|
|
<area id="property5" coords='6 70'/>
|
|
</areaset>
|
|
<area id="property6" coords="7 70"/>
|
|
<area id="property7" coords="8 70"/>
|
|
<area id="property8" coords="9 70"/>
|
|
<area id="property9" coords="10 70"/>
|
|
<area id="property10" coords="11 70"/>
|
|
<area id="property11" coords="12 70"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<property
|
|
name="propertyName"
|
|
column="column_name"
|
|
type="typename"
|
|
update="true|false"
|
|
insert="true|false"
|
|
formula="arbitrary SQL expression"
|
|
access="field|property|ClassName"
|
|
lazy="true|false"
|
|
unique="true|false"
|
|
not-null="true|false"
|
|
optimistic-lock="true|false"
|
|
node="element-name|@attribute-name|element/@attribute|."
|
|
index="index_name"
|
|
unique_key="unique_key_id"
|
|
length="L"
|
|
precision="P"
|
|
precision="S"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="property1">
|
|
<para>
|
|
<literal>name</literal>: el nombre de la propiedad, con la letra inicial
|
|
en minúsculas.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property2">
|
|
<para>
|
|
<literal>column</literal> (opcional - por defecto al nombre de la propiedad): el nombre
|
|
de la columna de tabla de base de datos mapeada. Esto puede también ser especificado
|
|
con elemento(s) <literal><column></literal> anidado(s).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property3">
|
|
<para>
|
|
<literal>type</literal> (opcional): un nombre que indica el nobre Hibernate.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property4-5">
|
|
<para>
|
|
<literal>update, insert</literal> (opcional - por defecto a <literal>true</literal>) :
|
|
especifica que las columnas mapeadas deben ser incluídas en las sentencias SQL
|
|
<literal>UPDATE</literal> y/o <literal>INSERT</literal> . Especificando ambas a
|
|
<literal>false</literal> permite una propiedad "derivada" cuyo valor es inicializado desde
|
|
alguna otra propiedad que mapee a la misma columna (o columnas) o por un disparador u otra
|
|
aplicación.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property6">
|
|
<para>
|
|
<literal>formula</literal> (opcional): una expresión SQL que define el valor
|
|
para una propiedad <emphasis>computada</emphasis>. Las propiedades computadas no tienen
|
|
una columna mapeada propia.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property7">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property8">
|
|
<para>
|
|
<literal>lazy</literal> (opcional - por defecto a <literal>false</literal>): Especifica
|
|
que esta propiedad debe ser traída perezosamente cuando la variable de instancia
|
|
sea accedida por primera vez (requiere instrumentación en tiempo de compilación).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property9">
|
|
<para>
|
|
<literal>unique</literal> (opcional): Habilita la generació DDL de una restricción
|
|
de unicidad para las columnas. Además, permite que ésta sea un blanco objetivo de
|
|
una <literal>property-ref</literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property10">
|
|
<para>
|
|
<literal>not-null</literal> (opcional): Habilita la generació DDL de una restricción
|
|
de nulabilidad para las columnas.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="property11">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica que las actualizaciones a esta propiedad requieran o no de la obtención
|
|
de un bloqueo optimista. En otras palabras, determina si debe ocurrir un incremento de versión
|
|
cuando la propiedad este sucia (desactualizada).
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
<emphasis>typename</emphasis> puede ser:
|
|
</para>
|
|
|
|
<orderedlist spacing="compact">
|
|
<listitem>
|
|
<para>
|
|
El nombre de un tipo básico Hibernate (por ejemplo, <literal>integer, string, character,
|
|
date, timestamp, float, binary, serializable, object, blob</literal>).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
El nombre de una clase Java de tipo básico (por ejemplo, <literal>int, float,
|
|
char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob</literal>).
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
El nombre de una clase Java serializable.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
El nombre de un tipo personalizado (por ejemplo, <literal>com.illflow.type.MyCustomType</literal>).
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>
|
|
Si no especificas un tipo, Hibernate usará reflección sobre la
|
|
propiedad mencionada para deducir el tipo Hibernate correcto. Hibernate intentará
|
|
interpretar el nombre de la clase de retorno del getter de la propiedad usando las reglas
|
|
2, 3 y 4 en ese orden. Sin embargo, esto no siempre suficiente. En ciertos casos, necesitarás
|
|
aún el atributo <literal>type</literal>. (Por ejemplo, para distinguir entre
|
|
<literal>Hibernate.DATE</literal> y <literal>Hibernate.TIMESTAMP</literal>,
|
|
o especificar un tipo personalizado.)
|
|
</para>
|
|
|
|
<para>
|
|
El atributo <literal>access</literal> te deja controlar cómo Hibernate
|
|
accederá a la propiedad en tiempo de ejecución. Por defecto, Hibernate
|
|
llamará al par de getter/setter de la propiedad. Si especificas
|
|
<literal>access="field"</literal>, Hibernate se saltará el par get/set y
|
|
accederá al campo directamente usando reflección. Puedes especificar tu
|
|
propia estrategia de acceso a la propiedad mencionando una clase que implemente
|
|
la interface <literal>org.hibernate.property.PropertyAccessor</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Una aspecto especialmente poderoso son las propiedades derivadas. Estas propiedades
|
|
son por definición de sólo lectura, el valor de la propiedad es computado
|
|
en tiempo de carga. Tu declaras la computación como una expresión SQL,
|
|
y ésta se traduce a cláusula de subconsulta <literal>SELECT</literal>
|
|
en la consulta SQL que cargue una instancia:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[
|
|
<property name="totalPrice"
|
|
formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
|
|
WHERE li.productId = p.productId
|
|
AND li.customerId = customerId
|
|
AND li.orderNumber = orderNumber )"/>]]></programlisting>
|
|
|
|
<para>
|
|
Observa que puedes referenciar la propia tabla de las entidades sin declarar un alias
|
|
o una columna particular (<literal>customerId</literal> en el ejemplo dado). Observa
|
|
además que puedes usar el elemento anidado de mapeo <literal><formula></literal>
|
|
si no te gusta usar el atributo.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-manytoone" revision="3">
|
|
<title>many-to-one</title>
|
|
|
|
<para>
|
|
Una asociación ordinaria a otra clase persistente se declara usando
|
|
el elemento <literal>many-to-one</literal>. El modelo relacional es una
|
|
asociación muchos-a-uno: una clave foránea en una tabla está
|
|
referenciando la columna (o columnas) de la clave primaria de la tabla objetivo.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="manytoone1" coords="2 70"/>
|
|
<area id="manytoone2" coords="3 70"/>
|
|
<area id="manytoone3" coords="4 70"/>
|
|
<area id="manytoone4" coords="5 70"/>
|
|
<area id="manytoone5" coords="6 70"/>
|
|
<areaset id="manytoone6-7" coords="">
|
|
<area id="manytoone6" coords='7 70'/>
|
|
<area id="manytoone7" coords='8 70'/>
|
|
</areaset>
|
|
<area id="manytoone8" coords="9 70"/>
|
|
<area id="manytoone9" coords="10 70"/>
|
|
<area id="manytoone10" coords="11 70"/>
|
|
<area id="manytoone11" coords="12 70"/>
|
|
<area id="manytoone12" coords="13 70"/>
|
|
<area id="manytoone13" coords="14 70"/>
|
|
<area id="manytoone14" coords="15 70"/>
|
|
<area id="manytoone15" coords="16 70"/>
|
|
<area id="manytoone16" coords="17 70"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<many-to-one
|
|
name="propertyName"
|
|
column="column_name"
|
|
class="ClassName"
|
|
cascade="cascade_style"
|
|
fetch="join|select"
|
|
update="true|false"
|
|
insert="true|false"
|
|
property-ref="propertyNameFromAssociatedClass"
|
|
access="field|property|ClassName"
|
|
unique="true|false"
|
|
not-null="true|false"
|
|
optimistic-lock="true|false"
|
|
lazy="true|proxy|false"
|
|
not-found="ignore|exception"
|
|
entity-name="EntityName"
|
|
formula="cualquier expresión SQL"
|
|
node="element-name|@attribute-name|element/@attribute|."
|
|
embed-xml="true|false"
|
|
index="index_name"
|
|
unique_key="unique_key_id"
|
|
foreign-key="foreign_key_name"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="manytoone1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone2">
|
|
<para>
|
|
<literal>column</literal> (opcional): El nombre de la columna clave foránea.
|
|
También puede ser especificado por uno o varios elementos anidados
|
|
<literal><column></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone3">
|
|
<para>
|
|
<literal>class</literal> (opcional - por defecto al tipo de la propiedad
|
|
determinado por reflección): El nombre de la clase asociada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone4">
|
|
<para>
|
|
<literal>cascade</literal> (opcional): Especifica qué operaciones deben
|
|
ir en cascada desde el objeto padre al objeto asociado
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone5">
|
|
<para>
|
|
<literal>fetch</literal> (opcional - por defecto a 1<literal>select</literal>):
|
|
Escoge entre recuperación outer-join o por selección secuencial.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone6-7">
|
|
<para>
|
|
<literal>update, insert</literal> (opcional - por defecto a <literal>true</literal>)
|
|
especifica que las columnas mapeadas deben ser incluídas en las sentencias SQL
|
|
<literal>UPDATE</literal> y/o <literal>INSERT</literal>. Establecer ambas a
|
|
<literal>false</literal> permite una asociación puramente "derivada" cuyo
|
|
valor es inicializado desde alguna otra propiedad que mapea a las misma columna (o columnas),
|
|
o por un disparador, o por otra aplicación.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone8">
|
|
<para>
|
|
<literal>property-ref</literal>: (opcional) El nombre de la propiedad de la clase
|
|
asociada que está unida a la clave foránea. Si no se especifica, se usa
|
|
la clave primaria de la clase asociada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone9">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone10">
|
|
<para>
|
|
<literal>unique</literal> (opcional): Habilita la generación DDL de una
|
|
restricción de unicidad para la columna de clave foránea. Además,
|
|
permite que ésta sea el objetivo de una <literal>property-ref</literal>.
|
|
Esto hace efectivamente la multiplicidad de la asociación uno a uno.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone11">
|
|
<para>
|
|
<literal>not-null</literal> (opcional): Habilita la generación DDL de una
|
|
restricción de nulabilidad para las columnas de clave foránea.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone12">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica que las actualizaciones a esta propiedad requieran o no la obtención
|
|
del bloqueo optimista. En otras palabras, determina si debe darse un incremento de versión
|
|
cuando esta propiedad esté desactualizada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone13">
|
|
<para>
|
|
<literal>lazy</literal> (opcional - por defecto a <literal>proxy</literal>):
|
|
Por defecto, las asociaciones de punto único van con proxies.
|
|
<literal>lazy="true"</literal> especifica que esta propiedad debe ser
|
|
traída perezosamente cuando la variable de instancia sea accedida por primera
|
|
vez (requiere instrumentación del bytecode en tiempo de compilación).
|
|
<literal>lazy="false"</literal> especifica que la asociación siempre será
|
|
recuperada tempranamente.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone14">
|
|
<para>
|
|
<literal>not-found</literal> (opcional - por defecto a <literal>exception</literal>):
|
|
Especifica cómo deben manejarse las claves foráneas que referencien
|
|
filas inexistentes: <literal>ignore</literal> tratará una fila perdida como
|
|
una asociación nula.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone15">
|
|
<para>
|
|
<literal>entity-name</literal> (opcional): El nombre de entidad de la clase
|
|
asociada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="manytoone16">
|
|
<para>
|
|
<literal>formula</literal> (opcional): una expresión SQL que define el valor
|
|
para una clave foránea <emphasis>computada</emphasis>.
|
|
</para>
|
|
</callout>
|
|
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Establecer el valor del atributo <literal>cascade</literal> a cualquier valor
|
|
significativo distinto de <literal>none</literal> propagará ciertas
|
|
operaciones al objeto asociado. Los valores significativos son los nombres de las
|
|
operaciones básicas de Hibernate, <literal>persist, merge, delete, save-update,
|
|
evict, replicate, lock, refresh</literal>, así como los valores especiales
|
|
<literal>delete-orphan</literal> y <literal>all</literal> y combinaciones de operaciones
|
|
separadas por coma, por ejemplo, <literal>cascade="persist,merge,evict"</literal> o
|
|
<literal>cascade="all,delete-orphan"</literal>. Para una explicación completa,
|
|
ver <xref linkend="objectstate-transitive"/>.
|
|
</para>
|
|
|
|
<para>
|
|
Una declaración típica <literal>muchos-a-uno</literal> se parece a esto:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<many-to-one name="product" class="Product" column="PRODUCT_ID"/>]]></programlisting>
|
|
|
|
<para>
|
|
El atributo <literal>property-ref</literal> debe ser usado solamente para el mapeo
|
|
de datos heredados donde una clave foránea referencia una clave única de
|
|
la tabla asociada, distinta de la clave primaria. Este es un modelo relacional feo.
|
|
Por ejemplo, supón que la clase <literal>Product</literal> tuviera un número
|
|
único serial que no es la clave primaria. (El atributo <literal>unique</literal>
|
|
controla la generación de DDL con la herramienta SchemaExport.)
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>]]></programlisting>
|
|
|
|
<para>
|
|
Entonces el mapeo para <literal>OrderItem</literal> debería usar:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>]]></programlisting>
|
|
|
|
<para>
|
|
Sin embargo, esto no esta ciertamente alentado.
|
|
</para>
|
|
|
|
<para>
|
|
Si la clave única referenciada abarca múltiples propiedades de la entidad asociada,
|
|
debes mapear las propiedades dentro de un elemento <literal><properties></literal>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-onetoone" revision="2">
|
|
<title>one-to-one</title>
|
|
|
|
<para>
|
|
Una asociación uno-a-uno a otra clase persistente se declara usando
|
|
un elemento <literal>one-to-one</literal>.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="onetoone1" coords="2 70"/>
|
|
<area id="onetoone2" coords="3 70"/>
|
|
<area id="onetoone3" coords="4 70"/>
|
|
<area id="onetoone4" coords="5 70"/>
|
|
<area id="onetoone5" coords="6 70"/>
|
|
<area id="onetoone6" coords="7 70"/>
|
|
<area id="onetoone7" coords="8 70"/>
|
|
<area id="onetoone8" coords="9 70"/>
|
|
<area id="onetoone9" coords="10 70"/>
|
|
<area id="onetoone10" coords="11 70"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<one-to-one
|
|
name="propertyName"
|
|
class="ClassName"
|
|
cascade="cascade_style"
|
|
constrained="true|false"
|
|
fetch="join|select"
|
|
property-ref="propertyNameFromAssociatedClass"
|
|
access="field|property|ClassName"
|
|
formula="cualquier expresión SQL"
|
|
lazy="true|proxy|false"
|
|
entity-name="EntityName"
|
|
node="element-name|@attribute-name|element/@attribute|."
|
|
embed-xml="true|false"
|
|
foreign-key="foreign_key_name"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="onetoone1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone2">
|
|
<para>
|
|
<literal>class</literal> (opcional - por defecto al tipo de la propiedad
|
|
determinado por reflección): El nombre de la clase asociada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone3">
|
|
<para>
|
|
<literal>cascade</literal> (opcional) especifica qué operaciones deben
|
|
ir en cascada desde el objeto padre al objeto asociado.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone4">
|
|
<para>
|
|
<literal>constrained</literal> (opcional) especifica que una restricción
|
|
de clave foránea de la tabla mapeada referencia a la tabla de la clase
|
|
asociada. Esta opción afecta el orden en que van en cascada
|
|
<literal>save()</literal> y <literal>delete()</literal>, y determina cuándo
|
|
la asociación pueden ser virtualizados por proxies (es también usado por
|
|
la herramienta de exportación de esquemas).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone5">
|
|
<para>
|
|
<literal>fetch</literal> (opcional - por defecto <literal>select</literal>):
|
|
Elige entre recuperación outer-join o recuperación por consulta secuencial.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone6">
|
|
<para>
|
|
<literal>property-ref</literal>: (opcional) El nombre de una propiedad de la clase
|
|
asociada que esté unida a la clave primaria de esta clase. Si no se especifica,
|
|
se usa la clave primaria de la clase asociada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone7">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone8">
|
|
<para>
|
|
<literal>formula</literal> (opcional): Casi todas las asociaciones uno-a-uno mapean
|
|
a la clave primaria de la entidad propietaria. En el raro caso en que este no sea el caso,
|
|
puedes especificar alguna otra columna, o columnas, o expresión para unir usando una
|
|
fórmula SQL. (Para un ejemplo ver <literal>org.hibernate.test.onetooneformula</literal>).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="onetoone9">
|
|
<para>
|
|
<literal>lazy</literal> (opcional - por defecto a <literal>proxy</literal>):
|
|
Por defecto, las asociaciones de punto único van con proxies.
|
|
<literal>lazy="true"</literal> especifica que esta propiedad debe ser
|
|
traída perezosamente cuando la variable de instancia sea accedida por primera
|
|
vez (requiere instrumentación del bytecode en tiempo de compilación).
|
|
<literal>lazy="false"</literal> especifica que la asociación siempre será
|
|
recuperada tempranamente. <emphasis>Observa que si <literal>constrained="false"</literal>,
|
|
la aplicación de proxies es imposible e Hibernate traerá temprano la
|
|
asociación!</emphasis>
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Hay dos variedades de asociaciones uno-a-uno:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
asociaciones de clave primaria
|
|
</para></listitem>
|
|
<listitem><para>
|
|
asociaciones de clave foráneas única
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
Las asociaciones de clave primaria no necesitan una columna de tabla extra; si dos filas
|
|
están relacionadas por la asociación entonces las dos filas de tablas comparten
|
|
el mismo valor de clave primaria. Por lo tanto, si quieres que dos objetos estén relacionados
|
|
por una asociación de clave primaria, debes asegurarte que se les asigne el mismo valor de
|
|
identificador!
|
|
</para>
|
|
|
|
<para>
|
|
Para una asociación de clave primaria, añade los siguientes mapeos a
|
|
<literal>Employee</literal> y <literal>Person</literal>, respectivamente.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<one-to-one name="person" class="Person"/>]]></programlisting>
|
|
<programlisting><![CDATA[<one-to-one name="employee" class="Employee" constrained="true"/>]]></programlisting>
|
|
|
|
<para>
|
|
Ahora debemos asegurarnos que las claves primarias de las filas relacionadas en las tablas
|
|
PERSON y EMPLOYEE sean iguales. Usamos una estrategia especial de generación de identificador
|
|
de Hibernate llamada <literal>foreign</literal>:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="person" table="PERSON">
|
|
<id name="id" column="PERSON_ID">
|
|
<generator class="foreign">
|
|
<param name="property">employee</param>
|
|
</generator>
|
|
</id>
|
|
...
|
|
<one-to-one name="employee"
|
|
class="Employee"
|
|
constrained="true"/>
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
A una instancia recién salvada de <literal>Person</literal> se le asigna entonces
|
|
el mismo valor de clave primaria con que la instancia <literal>Employee</literal>
|
|
referida por la propiedad <literal>employee</literal> de esta <literal>Person</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Alternativamente, una clave foránea con una restricción de unicidad, desde
|
|
<literal>Employee</literal> a <literal>Person</literal>, puede ser expresada como:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>]]></programlisting>
|
|
|
|
<para>
|
|
Y esta asociación puede hacerse bidireccional agregando lo siguiente al mapeo de
|
|
<literal>Person</literal> :
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<one-to-one name"employee" class="Employee" property-ref="person"/>]]></programlisting>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-naturalid">
|
|
<title>natural-id</title>
|
|
|
|
<programlisting><![CDATA[<natural-id mutable="true|false"/>
|
|
<property ... />
|
|
<many-to-one ... />
|
|
......
|
|
</natural-id>]]></programlisting>
|
|
|
|
<para>
|
|
Aunque recomendamos el uso de claves delegadas como claves primarias, todavía debes
|
|
intentar identificar claves naturales para todas las entidades. Una clave natural es una
|
|
propiedad o combinación de propiedades que es única y no nula. Si además
|
|
es inmutable, mejor aún. Mapea las propiedades de la clave natural dentro del elemento
|
|
<literal><natural-id></literal>. Hibernate generará las restricciones de clave
|
|
única y nulabilidad necesarias, y tu mapeo será más auto-documentado.
|
|
</para>
|
|
|
|
<para>
|
|
Recomendamos fuertemente que implementes <literal>equals()</literal> y
|
|
<literal>hashCode()</literal> para comparar las propiedades de clave natural
|
|
de la entidad.
|
|
</para>
|
|
|
|
<para>
|
|
Este mapeo no está concebido para usar con entidades con claves
|
|
primarias naturales.
|
|
</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem>
|
|
<para>
|
|
<literal>mutable</literal> (opcional, por defecto a <literal>false</literal>):
|
|
Por defecto, se asume que las propiedades de identificadores naturales son
|
|
inmutables (constantes).
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2 id="mapping-declaration-component" revision="2">
|
|
<title>component, dynamic-component</title>
|
|
|
|
<para>
|
|
El elemento <literal><component></literal> mapea propiedades de un objeto
|
|
hijo a columnas de la tabla de la clase padre. Los componentes pueden a su vez
|
|
declarar sus propias propiedades, componentes o colecciones. Ver debajo "Componentes".
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="component1" coords="2 45"/>
|
|
<area id="component2" coords="3 45"/>
|
|
<area id="component3" coords="4 45"/>
|
|
<area id="component4" coords="5 45"/>
|
|
<area id="component5" coords="6 45"/>
|
|
<area id="component6" coords="7 45"/>
|
|
<area id="component7" coords="8 45"/>
|
|
<area id="component8" coords="9 45"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<component
|
|
name="propertyName"
|
|
class="className"
|
|
insert="true|false"
|
|
update="true|false"
|
|
access="field|property|ClassName"
|
|
lazy="true|false"
|
|
optimistic-lock="true|false"
|
|
unique="true|false"
|
|
node="element-name|."
|
|
>
|
|
|
|
<property ...../>
|
|
<many-to-one .... />
|
|
........
|
|
</component>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="component1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component2">
|
|
<para>
|
|
<literal>class</literal> (opcional - por defecto al tipo de la propiedad
|
|
determinado por reflección): El nombre de la clase del componente (hijo).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component3">
|
|
<para>
|
|
<literal>insert</literal>: Aparecen las columnas mapeadas en
|
|
<literal>INSERT</literal>s SQL?
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component4">
|
|
<para>
|
|
<literal>update</literal>: Aparecen las columnas mapeadas en
|
|
<literal>UPDATE</literal>s SQL?
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component5">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component6">
|
|
<para>
|
|
<literal>lazy</literal> (opcional - por defecto a <literal>false</literal>): Especifica
|
|
que este componente debe ser recuperado perezosamente cuando la variable de instancia
|
|
sea accedida por primera vez (requiere instrumentación de bytecode en tiempo de
|
|
compilación).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component7">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica si las actualizaciones de este componente requieren o no la
|
|
adquisición de un bloqueo optimista. En otras palabras, determina si
|
|
debe ocurrir un incremento de versión cuando esta propiedad está
|
|
desactualizada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="component8">
|
|
<para>
|
|
<literal>unique</literal> (opcional - por defecto a <literal>false</literal>):
|
|
Especifica que existe una restricción de unicidad sobre todas las
|
|
columnas mapeadas del componente.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Las etiquetas hijas <literal><property></literal> mapean propiedades de la
|
|
clase hija columnas de la tabla.
|
|
</para>
|
|
|
|
<para>
|
|
El elemento <literal><component></literal> permite un subelemento
|
|
<literal><parent></literal> que mapea una propiedad de la clase del componente
|
|
como una referencia de regreso a la entidad contenedora.
|
|
</para>
|
|
|
|
<para>
|
|
El elemento <literal><dynamic-component></literal> permite que un
|
|
<literal>Map</literal> sea mapeado como un componente, donde los nombres de
|
|
las propiedades se corresponden a las claves del mapa, ver <xref linkend="components-dynamic"/>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-properties" revision="2">
|
|
<title>properties</title>
|
|
|
|
<para>
|
|
El elemento <literal><properties></literal> permite la definición de
|
|
un grupo de propiedades lógico con nombre de una clase. El uso más
|
|
importante de la contrucción es que permite que una combinación
|
|
de propiedades sea objetivo de una <literal>property-ref</literal>. Es también
|
|
una forma conveniente de definir una restricción de unicidad multicolumna.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="properties1" coords="2 45"/>
|
|
<area id="properties2" coords="3 45"/>
|
|
<area id="properties3" coords="4 45"/>
|
|
<area id="properties4" coords="5 45"/>
|
|
<area id="properties5" coords="6 45"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<properties
|
|
name="logicalName"
|
|
insert="true|false"
|
|
update="true|false"
|
|
optimistic-lock="true|false"
|
|
unique="true|false"
|
|
>
|
|
|
|
<property ...../>
|
|
<many-to-one .... />
|
|
........
|
|
</properties>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="properties1">
|
|
<para>
|
|
<literal>name</literal>: El nombre lógico del agrupamiento -
|
|
<emphasis>no</emphasis> un nombre de propiedad real.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="properties2">
|
|
<para>
|
|
<literal>insert</literal>: Aparecen las columnas mapeadas en
|
|
<literal>INSERT</literal>s SQL?
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="properties3">
|
|
<para>
|
|
<literal>update</literal>: Aparecen las columnas mapeadas en
|
|
<literal>UPDATE</literal>s SQL?
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="properties4">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica si las actualizaciones de estas propiedades requieren o no de la
|
|
adquisición de un bloqueo optimista. En otras palabras, determina si
|
|
debe ocurrir un incremento de versión cuando estas propiedades están
|
|
desactualizadas.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="properties5">
|
|
<para>
|
|
<literal>unique</literal> (opcional - por defecto a <literal>false</literal>):
|
|
Especifica que existe una restricción de unicidad sobre todas las
|
|
columnas mapeadas del componente.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Por ejemplo, si tenemos el siguiente mapeo de <literal><properties></literal>:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Person">
|
|
<id name="personNumber"/>
|
|
...
|
|
<properties name="name"
|
|
unique="true" update="false">
|
|
<property name="firstName"/>
|
|
<property name="initial"/>
|
|
<property name="lastName"/>
|
|
</properties>
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
Entonces puede que tengamos alguna asociación de datos heredados que se refiera
|
|
a esta clave única de la tabla de <literal>Person</literal>, en vez de la clave
|
|
primaria:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<many-to-one name="person"
|
|
class="Person" property-ref="name">
|
|
<column name="firstName"/>
|
|
<column name="initial"/>
|
|
<column name="lastName"/>
|
|
</many-to-one>]]></programlisting>
|
|
|
|
<para>
|
|
No recomendamos el uso de este tipo de cosas fuera del contexto del mapeo de
|
|
datos heredados.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-subclass" revision="3">
|
|
<title>subclass</title>
|
|
|
|
<para>
|
|
Finalmente, la persistencia polimórfica requiere la declaración
|
|
de la clase persistente raíz. Para la estrategia de mapeo
|
|
tabla-por-jerarquía-de-clases, se usa la declaración de
|
|
<literal><subclass></literal>.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="subclass1" coords="2 55"/>
|
|
<area id="subclass2" coords="3 55"/>
|
|
<area id="subclass3" coords="4 55"/>
|
|
<area id="subclass4" coords="5 55"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<subclass
|
|
name="ClassName"
|
|
discriminator-value="discriminator_value"
|
|
proxy="ProxyInterface"
|
|
lazy="true|false"
|
|
dynamic-update="true|false"
|
|
dynamic-insert="true|false"
|
|
entity-name="EntityName"
|
|
node="element-name">
|
|
|
|
<property .... />
|
|
.....
|
|
</subclass>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="subclass1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de clase cualificado completamente
|
|
de la subclase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="subclass2">
|
|
<para>
|
|
<literal>discriminator-value</literal> (opcional - por defecto al nombre de la clase):
|
|
Un valor que distingue a subclases individuales.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="subclass3">
|
|
<para>
|
|
<literal>proxy</literal> (opcional): Especifica una clase o interface a usar para
|
|
proxies de inicialización perezosa.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="subclass4">
|
|
<para>
|
|
<literal>lazy</literal> (opcional, por defecto a <literal>true</literal>):
|
|
Establecer <literal>lazy="false"</literal> deshabilita el uso de recuperación
|
|
perezosa.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Cada subclase debe declarar sus propias propiedades persistentes y subclases.
|
|
Se asume que las propiedades <literal><version></literal> y <literal><id></literal>
|
|
son heredadas de la clase raíz. Cada subclase en una jerarquía debe
|
|
definir un <literal>discriminator-value</literal> único. Si no se especifica ninguno,
|
|
se usa el nombre completamente cualificado de clase Java.
|
|
</para>
|
|
|
|
<para>
|
|
Es posible definir mapeos <literal>subclass</literal>, <literal>union-subclass</literal>,
|
|
y <literal>joined-subclass</literal> en documentos de mapeo separados, directamente debajo
|
|
de <literal>hibernate-mapping</literal>. Esto te permite extender una jerarquía de clases
|
|
con sólo agregar un nuevo fichero de mapeo. Debes especificar un atributo
|
|
<literal>extends</literal> en el mapeo de la subclase, mencionando una superclase previamente mapeada.
|
|
Nota: Previamente esta funcionalidad hacía importante el orden de los documentos de mapeo.
|
|
Desde Hibernate3, el orden de los ficheros de mapeo no importa cuando se usa la palabra reservada
|
|
extends. El orden dentro de un mismo fichero de mapeo todavía necesita ser definido como
|
|
superclases antes de subclases.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[
|
|
<hibernate-mapping>
|
|
<subclass name="DomesticCat" extends="Cat" discriminator-value="D">
|
|
<property name="name" type="string"/>
|
|
</subclass>
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
Para información acerca de mapeos de herencia, ver <xref linkend="inheritance"/>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-joinedsubclass" revision="3">
|
|
<title>joined-subclass</title>
|
|
|
|
<para>
|
|
Alternativamente, cada subclase puede ser mapeada a su propia tabla
|
|
(estrategia de mapeo tabla-por-subclase). El estado heredado se recupera
|
|
uniendo con la tabla de la superclase.
|
|
Usamos el elemento <literal><joined-subclass></literal>.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="joinedsubclass1" coords="2 45"/>
|
|
<area id="joinedsubclass2" coords="3 45"/>
|
|
<area id="joinedsubclass3" coords="4 45"/>
|
|
<area id="joinedsubclass4" coords="5 45"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<joined-subclass
|
|
name="ClassName"
|
|
table="tablename"
|
|
proxy="ProxyInterface"
|
|
lazy="true|false"
|
|
dynamic-update="true|false"
|
|
dynamic-insert="true|false"
|
|
schema="schema"
|
|
catalog="catalog"
|
|
extends="SuperclassName"
|
|
persister="ClassName"
|
|
subselect="SQL expression"
|
|
entity-name="EntityName"
|
|
node="element-name">
|
|
|
|
<key .... >
|
|
|
|
<property .... />
|
|
.....
|
|
</joined-subclass>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="joinedsubclass1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de clase completamente cualificado de
|
|
la subclase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="joinedsubclass2">
|
|
<para>
|
|
<literal>table</literal>: El nombre de tabla de la subclase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="joinedsubclass3">
|
|
<para>
|
|
<literal>proxy</literal> (opcional): Especifica una clase o interface a
|
|
usar para proxies de inicializacón perezosa.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="joinedsubclass4">
|
|
<para>
|
|
<literal>lazy</literal> (opcional, por defecto a <literal>true</literal>):
|
|
Establecer <literal>lazy="false"</literal> deshabilita el uso de recuperación
|
|
perezosa.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
No se requiere de una columna discriminadora para esta estrategia de mapeo. Cada subclase debe,
|
|
sin embargo, declarar una columna de tabla que tenga el identificador del objeto usando el
|
|
elemento <literal><key></literal>. El mapeo del comienzo del capítulo
|
|
debería ser reescrito como:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<?xml version="1.0"?>
|
|
<!DOCTYPE hibernate-mapping PUBLIC
|
|
"-//Hibernate/Hibernate Mapping DTD//EN"
|
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
|
|
|
<hibernate-mapping package="eg">
|
|
|
|
<class name="Cat" table="CATS">
|
|
<id name="id" column="uid" type="long">
|
|
<generator class="hilo"/>
|
|
</id>
|
|
<property name="birthdate" type="date"/>
|
|
<property name="color" not-null="true"/>
|
|
<property name="sex" not-null="true"/>
|
|
<property name="weight"/>
|
|
<many-to-one name="mate"/>
|
|
<set name="kittens">
|
|
<key column="MOTHER"/>
|
|
<one-to-many class="Cat"/>
|
|
</set>
|
|
<joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
|
|
<key column="CAT"/>
|
|
<property name="name" type="string"/>
|
|
</joined-subclass>
|
|
</class>
|
|
|
|
<class name="eg.Dog">
|
|
<!-- mapping for Dog could go here -->
|
|
</class>
|
|
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
Para información acerca de mapeos de herencia, ver <xref linkend="inheritance"/>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-unionsubclass" revision="2">
|
|
<title>union-subclass</title>
|
|
|
|
<para>
|
|
Una tercera opción es mapear sólo las clases concretas de una
|
|
jerarquía de clases a tablas, (la estrategia tabla-por-clase-concreta)
|
|
donde cada tabla define todo el estado persistente de la clase, incluyendo el
|
|
estado heredado. En Hibernate, no es absolutamente necesario mapear dichas
|
|
jerarquías de herencia. Puedes simplemente mapear cada clase con una
|
|
declaración <literal><class></literal> separada. Sin embargo,
|
|
si deseas usar asociaciones polimórficas (por ejemplo, una asociación
|
|
a la superclase de tu jerarquía), debes usar el mapeo
|
|
<literal><union-subclass></literal>.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="unionsubclass1" coords="2 45"/>
|
|
<area id="unionsubclass2" coords="3 45"/>
|
|
<area id="unionsubclass3" coords="4 45"/>
|
|
<area id="unionsubclass4" coords="5 45"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<union-subclass
|
|
name="ClassName"
|
|
table="tablename"
|
|
proxy="ProxyInterface"
|
|
lazy="true|false"
|
|
dynamic-update="true|false"
|
|
dynamic-insert="true|false"
|
|
schema="schema"
|
|
catalog="catalog"
|
|
extends="SuperclassName"
|
|
abstract="true|false"
|
|
persister="ClassName"
|
|
subselect="SQL expression"
|
|
entity-name="EntityName"
|
|
node="element-name">
|
|
|
|
<property .... />
|
|
.....
|
|
</union-subclass>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="unionsubclass1">
|
|
<para>
|
|
<literal>name</literal>: El nombre de clase completamente cualificado de la subclase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="unionsubclass2">
|
|
<para>
|
|
<literal>table</literal>: El nombre de tabla de la subclase.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="unionsubclass3">
|
|
<para>
|
|
<literal>proxy</literal> (optional): Especifica una clase o interface a
|
|
usar para proxies de inicializacón perezosa.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="unionsubclass4">
|
|
<para>
|
|
<literal>lazy</literal> (opcional, por defecto a <literal>true</literal>):
|
|
Establecer <literal>lazy="false"</literal> deshabilita el uso de recuperación
|
|
perezosa.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
No se requiere columna o columna clave discriminadora para esta estrategia de mapeo.
|
|
</para>
|
|
|
|
<para>
|
|
Para información acerca de mapeos de herencia, ver <xref linkend="inheritance"/>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-join" revision="3">
|
|
<title>join</title>
|
|
|
|
<para>
|
|
Usando el elemento <literal><join></literal>, es posible mapear
|
|
propiedades de una clase a varias tablas.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="join1" coords="2 50"/>
|
|
<area id="join2" coords="3 50"/>
|
|
<area id="join3" coords="4 50"/>
|
|
<area id="join4" coords="5 50"/>
|
|
<area id="join5" coords="6 50"/>
|
|
<area id="join6" coords="7 50"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<join
|
|
table="tablename"
|
|
schema="owner"
|
|
catalog="catalog"
|
|
fetch="join|select"
|
|
inverse="true|false"
|
|
optional="true|false">
|
|
|
|
<key ... />
|
|
|
|
<property ... />
|
|
...
|
|
</join>]]></programlisting>
|
|
|
|
<calloutlist>
|
|
<callout arearefs="join1">
|
|
<para>
|
|
<literal>table</literal>: El nombre de la clase unida.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join2">
|
|
<para>
|
|
<literal>schema</literal> (opcional): Sobrescribe el nombre de esquema
|
|
especificado por el elemento raíz <literal><hibernate-mapping></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join3">
|
|
<para>
|
|
<literal>catalog</literal> (opcional): Sobrescribe el nombre de catálogo
|
|
especificado por el elemento raíz <literal><hibernate-mapping></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join4">
|
|
<para>
|
|
<literal>fetch</literal> (opcional - por defecto a <literal>join</literal>):
|
|
Si se establece a <literal>join</literal>, por defecto, Hibernate usará
|
|
una unión interior (inner join) para recuperar un <literal><join></literal>
|
|
definido por una clase o sus superclases y una unión externa (outer join)
|
|
para un <literal><join></literal> definido por una subclase.
|
|
Si se establece a <literal>select</literal>, entonces Hibernate usará una
|
|
select secuencial para un <literal><join></literal> definido en una subclase,
|
|
que será publicada sólo si una fila resulta representar una instancia
|
|
de la subclase. Las uniones interiores todavía serán usados para
|
|
recuperar un <literal><join></literal> definido por la clase y sus superclases.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join5">
|
|
<para>
|
|
<literal>inverse</literal> (opcional - por defecto a <literal>false</literal>):
|
|
De habilitarse, Hibernate no intentará insertar o actualizar las propiedades
|
|
definidas por esta unión.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="join6">
|
|
<para>
|
|
<literal>optional</literal> (opcional - por defecto a <literal>false</literal>):
|
|
De habilitarse, Hibernate insertará una fila sólo si las propiedades
|
|
definidas por esta unión son no nulas y siempre usará una unión
|
|
externa para recuperar las propiedades.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Por ejemplo, la información domiciliaria de una persona puede ser mapeada
|
|
a una tabla separada (preservando a la vez la semántica de tipo de valor para
|
|
todas las propiedades):
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Person"
|
|
table="PERSON">
|
|
|
|
<id name="id" column="PERSON_ID">...</id>
|
|
|
|
<join table="ADDRESS">
|
|
<key column="ADDRESS_ID"/>
|
|
<property name="address"/>
|
|
<property name="zip"/>
|
|
<property name="country"/>
|
|
</join>
|
|
...]]></programlisting>
|
|
|
|
<para>
|
|
Esta funcionalidad es a menudo solamente útil para modelos de datos
|
|
heredados; recomendamos menos tablas que clases un modelo de dominio más
|
|
granularizado. Sin embargo, es útil para cambiar entre estrategias de mapeo
|
|
de herencias en una misma jerarquía, como se explica luego.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-key">
|
|
<title>key</title>
|
|
|
|
<para>
|
|
Hasta ahora hemos visto el elemento <literal><key></literal> pocas veces.
|
|
Aparece en cualquier sitio en que el elemento padre de mapeo defina una unión
|
|
a una nueva tabla, y define la clave foránea en la tabla unida,
|
|
que referencia la clave primaria de la tabla original.
|
|
</para>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="key1" coords="2 50"/>
|
|
<area id="key2" coords="3 50"/>
|
|
<area id="key3" coords="4 50"/>
|
|
<area id="key4" coords="5 50"/>
|
|
<area id="key5" coords="6 50"/>
|
|
<area id="key6" coords="7 50"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<key
|
|
column="columnname"
|
|
on-delete="noaction|cascade"
|
|
property-ref="propertyName"
|
|
not-null="true|false"
|
|
update="true|false"
|
|
unique="true|false"
|
|
/>]]></programlisting>
|
|
|
|
<calloutlist>
|
|
<callout arearefs="key1">
|
|
<para>
|
|
<literal>column</literal> (opcional): El nombre de columna de la clave foránea.
|
|
Puede ser también especificado por elemento(s) anidado(s)
|
|
<literal><column></literal>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="key2">
|
|
<para>
|
|
<literal>on-delete</literal> (opcional, por defecto a <literal>noaction</literal>):
|
|
Especifica si la restricción de clave foránea tiene el borrado en cascada
|
|
habilitado a nivel de base de datos.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="key3">
|
|
<para>
|
|
<literal>property-ref</literal> (opcional): Especifica que la clave foránea
|
|
referencia columnas que no son del la clave primaria de la tabla original.
|
|
(Provisto para datos heredados.)
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="key4">
|
|
<para>
|
|
<literal>not-null</literal> (opcional): Especifica que las columnas de la clave
|
|
foránea son no nulables (esto está implicado si la clave foránea
|
|
es también parte de la clave primaria).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="key5">
|
|
<para>
|
|
<literal>update</literal> (opcional): Especifica que la clave foránea nunca
|
|
debe ser actualizada (esto está implicado si la clave foránea
|
|
es también parte de la clave primaria).
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="key6">
|
|
<para>
|
|
<literal>unique</literal> (opcional): Especifica que la clave foránea
|
|
debe tener una restricción de unicidad (esto está implicado si
|
|
la clave foránea es también la clave primaria).
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
<para>
|
|
Recomendamos que, para los sistemas en donde el rendimiento sea importante, todas las
|
|
claves deben ser definidas <literal>on-delete="cascade"</literal>, e Hibernate usará
|
|
una restricción <literal>ON CASCADE DELETE</literal> a nivel de base de datos,
|
|
en vez de muchas sentencias <literal>DELETE</literal> individuales. Ten en cuenta que
|
|
esta funcionalidad se salta la habitual estrategia de bloqueo optimista de Hibernate para
|
|
datos versionados.
|
|
</para>
|
|
|
|
<para>
|
|
Los atributos <literal>not-null</literal> y <literal>update</literal> son útiles
|
|
al mapear una asociación uno a muchos unidireccional. Si mapeas una uno a muchos
|
|
unidireccional a una clave foránea no nulable, <emphasis>debes</emphasis> declarar
|
|
la columna clave usando <literal><key not-null="true"></literal>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-column" revision="3">
|
|
<title>los elementos column y formula</title>
|
|
<para>
|
|
Cualquier elemento de mapeo que acepte un atributo <literal>column</literal> aceptará
|
|
alternativamente un subelemento <literal><column></literal>. De forma similar,
|
|
<literal><formula></literal> es una alternativa al atributo <literal>formula</literal>.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<column
|
|
name="column_name"
|
|
length="N"
|
|
precision="N"
|
|
scale="N"
|
|
not-null="true|false"
|
|
unique="true|false"
|
|
unique-key="multicolumn_unique_key_name"
|
|
index="index_name"
|
|
sql-type="sql_type_name"
|
|
check="SQL expression"/>]]></programlisting>
|
|
|
|
<programlisting><![CDATA[<formula>expresión SQL</formula>]]></programlisting>
|
|
|
|
<para>
|
|
Los atributos <literal>column</literal> y <literal>formula</literal> pueden
|
|
incluso ser combinados dentro del mismo mapeo de propiedad o asociación para
|
|
expresar, por ejemplo, condiciones de unión exóticas.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<many-to-one name="homeAddress" class="Address"
|
|
insert="false" update="false">
|
|
<column name="person_id" not-null="true" length="10"/>
|
|
<formula>'MAILING'</formula>
|
|
</many-to-one>]]></programlisting>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-declaration-import">
|
|
<title>import</title>
|
|
|
|
<para>
|
|
Supón que tu aplicación tiene dos clases persistentes con el mismo nombre,
|
|
y no quieres especificar el nombre completamenta cualificado (paquete) en las consultas
|
|
Hibernate. Las clases pueden ser "importadas" explícitamente, en vez de confiar en
|
|
<literal>auto-import="true"</literal>. Puedes incluso importar clases e interfaces que
|
|
no estén mapeadas explícitamente.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<import class="java.lang.Object" rename="Universe"/>]]></programlisting>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="import1" coords="2 40"/>
|
|
<area id="import2" coords="3 40"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<import
|
|
class="ClassName"
|
|
rename="ShortName"
|
|
/>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="import1">
|
|
<para>
|
|
<literal>class</literal>: El nombre de clase completamente cualificado de
|
|
cualquier clase Java.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="import2">
|
|
<para>
|
|
<literal>rename</literal> (opcional - por defecto al nombre de clase sin cualificar):
|
|
Un nombre que será usado en el leguaje de consulta.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-types-anymapping" revision="2">
|
|
<title>any</title>
|
|
|
|
<para>
|
|
Hay un tipo más de mapeo de propiedad. El elemento de mapeo <literal><any></literal>
|
|
define una asociacián polimórfica a clases desde múltiples tablas. Este tipo
|
|
de mapeo siempre requiere más de una columna. La primera columna contiene el tipo de la
|
|
entidad asociada. Las columnas restantes contienen el identificador. Es imposible especificar una
|
|
restricción de clave foránea para este tipo de asociación, por lo que
|
|
esto ciertamente no está concebido como la forma habitual de mapear asociaciones
|
|
(polimórficas). Sólo debes usar esto en casos muy especiales (por ejemplo,
|
|
trazas de auditoréa, datos de sesión de usuario, etc).
|
|
</para>
|
|
|
|
<para>
|
|
El atributo <literal>meta-type</literal> permite a la aplicación especificar un tipo
|
|
personalizado que mapee columnas de base de datos a clases persistentes que tengan propiedades
|
|
identificadoras del tipo especificado por <literal>id-type</literal>. Debes especificar el
|
|
mapeo de valores del meta-type a nombres de clase.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<any name="being" id-type="long" meta-type="string">
|
|
<meta-value value="TBL_ANIMAL" class="Animal"/>
|
|
<meta-value value="TBL_HUMAN" class="Human"/>
|
|
<meta-value value="TBL_ALIEN" class="Alien"/>
|
|
<column name="table_name"/>
|
|
<column name="id"/>
|
|
</any>]]></programlisting>
|
|
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="any1" coords="2 50"/>
|
|
<area id="any2" coords="3 50"/>
|
|
<area id="any3" coords="4 50"/>
|
|
<area id="any4" coords="5 50"/>
|
|
<area id="any5" coords="6 50"/>
|
|
<area id="any6" coords="7 50"/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[<any
|
|
name="propertyName"
|
|
id-type="idtypename"
|
|
meta-type="metatypename"
|
|
cascade="cascade_style"
|
|
access="field|property|ClassName"
|
|
optimistic-lock="true|false"
|
|
>
|
|
<meta-value ... />
|
|
<meta-value ... />
|
|
.....
|
|
<column .... />
|
|
<column .... />
|
|
.....
|
|
</any>]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="any1">
|
|
<para>
|
|
<literal>name</literal>: el nombre de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="any2">
|
|
<para>
|
|
<literal>id-type</literal>: el tipo del identificador.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="any3">
|
|
<para>
|
|
<literal>meta-type</literal> (opcional - por defecto a <literal>string</literal>):
|
|
Cualquier tipo que sea permitido para un mapeo de discriminador.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="any4">
|
|
<para>
|
|
<literal>cascade</literal> (opcional- por defecto a <literal>none</literal>):
|
|
el estilo de cascada.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="any5">
|
|
<para>
|
|
<literal>access</literal> (opcional - por defecto a <literal>property</literal>): La
|
|
estrategia que Hibernate debe usar para acceder al valor de la propiedad.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="any6">
|
|
<para>
|
|
<literal>optimistic-lock</literal> (opcional - por defecto a <literal>true</literal>):
|
|
Especifica si las actualizaciones de esta propiedad requieren o no de la
|
|
adquisición del bloqueo optimista. En otras palabras, determina si debe ocurrir
|
|
un incremento de versión cuando esta propiedad está desactualizada.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="mapping-types">
|
|
<title>Tipos de Hibernate</title>
|
|
|
|
<sect2 id="mapping-types-entitiesvalues" revision="1">
|
|
<title>Entidades y Valores</title>
|
|
|
|
<para>
|
|
Para entender el comportamiento de varios objetos a nivel de lenguaje Java
|
|
con respecto al servicio de persistencia, necesitamos clasificarlos en dos grupos:
|
|
</para>
|
|
|
|
<para>
|
|
Una <emphasis>entidad</emphasis> existe independientemente de cualquier otros
|
|
objetos que referencien a la entidad. Contrasta esto con el model habitual de Java
|
|
donde un objeto desreferenciado es recolectado como basura. Las entidades deben ser
|
|
salvadas y borradas explícitamente (excepto que las grabaciones y borrados
|
|
puedan ser <emphasis>tratados en cascada</emphasis> desde una entidad padre a sus hijos).
|
|
Esto es diferente al modelo de persistencia de objetos por alcance - y se corresponde
|
|
más de cerca a cómo los objetos de aplicación son usados
|
|
habitualmente en grandes sistemas. Las entidades soportan referencias circulares y
|
|
compartidas, que tambié pueden ser versionadas.
|
|
</para>
|
|
|
|
<para>
|
|
El estado persistente de una entidad consiste en referencias a otras entidades
|
|
e instancias de tipo <emphasis>valor</emphasis>. Los valores son primitivos,
|
|
colecciones (no lo que está dentro de la colección), componentes
|
|
y ciertos objetos inmutables. A diferencia de las entidades, los valores
|
|
(en particular las colecciones y los componentes) <emphasis>son</emphasis>
|
|
hechos persitentes y borrados por alcance. Como los objetos valor (y primitivos)
|
|
son persistidos y borrados junto a sus entidades contenedoras, no pueden ser
|
|
versionados independientemente. Los valores no tienen identidad independiente,
|
|
por los que no pueden ser compartidos por dos entidades o colleciones.
|
|
</para>
|
|
|
|
<para>
|
|
Hasta ahora, hemos estado usando el término "clase persistente"
|
|
para referirnos a entidades. Continuaremos haciéndolo. Hablando
|
|
estrictamente, sin embargo, no todas la clases con estado persistente
|
|
definidas por el usuario son entidades. Un <emphasis>componente</emphasis>
|
|
es una clase definida por el usuario con semántica de valor.
|
|
Una propiedad Java de tipo <literal>java.lang.String</literal> también
|
|
tiene semántica de valor. Dada esta definición, podemos decir
|
|
que todos los tipo (clases) provistos por el JDK tienen una semántica
|
|
de tipo valor en Java, mientras que los tipos definidos por el usuario
|
|
pueden ser mapeados con semántica de tipo valor o de entidad.
|
|
La desición corre por cuenta del desarrollador de la aplicación.
|
|
Un buen consejo para una clase entidad en un modelo de dominio son las referencias
|
|
compartidas a una sola instancia de esa clase, mientras que la composición
|
|
o agregación usualmente se traducen a un tipo de valor.
|
|
</para>
|
|
|
|
<para>
|
|
Volveremos a visitar ambos conceptos a lo largo de la documentación.
|
|
</para>
|
|
|
|
<para>
|
|
EL desafío es mapear el sistema de tipos de Java (y la definición
|
|
de entidades y tipos de valor de los desarrolladores) al sistema de tipos de
|
|
SQL/base de datos. EL puente entre ambos sistemas es provisto por Hibernate:
|
|
para las entidades usamos <literal><class></literal>,
|
|
<literal><subclass></literal>, etc. Para los tipos de valor usamos
|
|
<literal><property></literal>, <literal><component></literal>, etc,
|
|
usualmente con un atributo <literal>type</literal>. El valor de este atributo
|
|
es el nombre de un <emphasis>tipo de mapeo</emphasis> de Hibernate. Hibernate
|
|
provee de fábrica muchos mapeos (para tipos de valores del JDK
|
|
estándar). Puedes escribir tus propios mapeos de tipo, así como
|
|
implementar tus estrategias de conversión personalizadas, como veremos luego.
|
|
</para>
|
|
|
|
<para>
|
|
Todos los tipos prefabricados de Hibernate soportan semántica de nulos
|
|
excepto las colecciones.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-types-basictypes" revision="2">
|
|
<title>Tipos de valores básicos</title>
|
|
|
|
<para>
|
|
Los <emphasis>tipos de mapeo básicos</emphasis> prefabricados pueden ser
|
|
categorizado a grandes rasgos en:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>integer, long, short, float, double, character, byte,
|
|
boolean, yes_no, true_false</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipos primitivos de Java o clases de envoltura a
|
|
la tipos de columna SQL (especícifica del vendedor).
|
|
<literal>boolean, yes_no</literal> y <literal>true_false</literal>
|
|
son codificaciones alternativas a <literal>boolean</literal> de
|
|
Java o <literal>java.lang.Boolean</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>string</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Un mapeo del tipo <literal>java.lang.String</literal> a
|
|
<literal>VARCHAR</literal> (u Oracle <literal>VAARCHAR2</literal>).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>date, time, timestamp</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipo desde <literal>java.util.Date</literal> y sus subclases
|
|
a tipos SQL <literal>DATE</literal>, <literal>TIME</literal> y
|
|
<literal>TIMESTAMP</literal> (o equivalente).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>calendar, calendar_date</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipo desde <literal>java.util.Date</literal> y sus subclases
|
|
a tipos SQL <literal>TIMESTAMP</literal> y <literal>DATE</literal>
|
|
(o equivalente).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>big_decimal, big_integer</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipo desde <literal>java.math.BigDecimal</literal> y
|
|
<literal>java.math.BigInteger</literal> a <literal>NUMERIC</literal>
|
|
(o <literal>NUMBER</literal> de Oracle).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>locale, timezone, currency</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipo desde <literal>java.util.Locale</literal>,
|
|
<literal>java.util.TimeZone</literal> y
|
|
<literal>java.util.Currency</literal> a
|
|
<literal>VARCHAR</literal> (o <literal>VARCHAR2</literal> de Oracle).
|
|
Las instancias de <literal>Locale</literal> y <literal>Currency</literal>
|
|
son mapeadas a sus códigos ISO. Las instancias de
|
|
<literal>TimeZone</literal> son mapeadas a sus <literal>ID</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>class</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Un mapeo de tipo <literal>java.lang.Class</literal> a
|
|
<literal>VARCHAR</literal> (o <literal>VARCHAR2</literal> de Oracle).
|
|
Una <literal>Class</literal> es mapeara a su nombre completamente
|
|
cualificado.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>binary</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapea arreglos de bytes a un tipo binario SQL apropiado.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>text</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapea cadenas largas Java al tipo SQL <literal>CLOB</literal> o
|
|
<literal>TEXT</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>serializable</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapea tipos serializables Java a un tipo binario SQL apropiado.
|
|
Puedes además indicar el tipo <literal>serializable</literal>
|
|
de Hibernate con el nombre de una clase o interface serializable Java
|
|
que no sea por defecto un tipo básico.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>clob, blob</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Mapeos de tipo para las clases JDBC <literal>java.sql.Clob</literal> y
|
|
<literal>java.sql.Blob</literal>. Estos tipos pueden ser inconvenientes
|
|
para algunas aplicaciones, pues el objeto blob o clob no puede ser reusado
|
|
fuera de una transacción (Además, el soporte del driver suele
|
|
ser malo e inconsistente).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</para>
|
|
|
|
<para>
|
|
Los identificadores únicos de entidades y collecciones pueden ser de cualquier
|
|
tipo básico excepto <literal>binary</literal>, <literal>blob</literal>
|
|
y <literal>clob</literal>.
|
|
(Los identificadores compuestos están también permitidos, ver debajo.)
|
|
</para>
|
|
|
|
<para>
|
|
Los tipos de valor básicos tienen sus constantes <literal>Type</literal>
|
|
correspondientes definidas en <literal>org.hibernate.Hibernate</literal>. Por ejemplo,
|
|
<literal>Hibernate.STRING</literal> representa el tipo <literal>string</literal>.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-types-custom" revision="2">
|
|
<title>Tipos de valor personalizados</title>
|
|
|
|
<para>
|
|
Es relativamente fácil para los desarrolladores crear sus propios tipos de valor.
|
|
Por ejemplo, podrías querer persistir propiedades del tipo <literal>java.lang.BigInteger</literal>
|
|
a columnas <literal>VARCHAR</literal>. Hibernate no provee un tipo de fábrica para esto.
|
|
Pero los tipos personalizados no están limitados a mapear una propiedad (o elemento de colección)
|
|
a una sola columna de tabla. Así, por ejemplo, podrías tener una propiedad Java
|
|
<literal>getName()</literal>/<literal>setName()</literal> de tipo <literal>java.lang.String</literal>
|
|
que fuera persistida a las columnas <literal>FIRST_NAME</literal>, <literal>INITIAL</literal>,
|
|
<literal>SURNAME</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Para implementar un tipo personalizado, implementa bien <literal>org.hibernate.UserType</literal>
|
|
o <literal>org.hibernate.CompositeUserType</literal> y declara las propiedades usando el nombre
|
|
de clase completamente cualificado del tipo. Revisa <literal>org.hibernate.test.DoubleStringType</literal>
|
|
para ver qué tipo de cosas son posibles.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<property name="twoStrings" type="org.hibernate.test.DoubleStringType">
|
|
<column name="first_string"/>
|
|
<column name="second_string"/>
|
|
</property>]]></programlisting>
|
|
|
|
<para>
|
|
Observa el uso de etiquetas <literal><column></literal> para mapear una propiedad
|
|
a múltiples columnas.
|
|
</para>
|
|
|
|
<para>
|
|
Las interfaces <literal>CompositeUserType</literal>, <literal>EnhancedUserType</literal>,
|
|
<literal>UserCollectionType</literal>, y <literal>UserVersionType</literal> proveen
|
|
soporte a usos más especializados.
|
|
</para>
|
|
|
|
<para>
|
|
Puedes incluso proveer de parámetros a un <literal>UserType</literal> en el
|
|
fichero de mapeo. Para hacer esto, tu <literal>UserType</literal> debe implementar
|
|
la interface <literal>org.hibernate.usertype.ParameterizedType</literal>. Para
|
|
proveer de parámetros a tu tipo personalizado, puedes usar el elemento
|
|
<literal><type></literal> en tus ficheros de mapeo.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<property name="priority">
|
|
<type name="com.mycompany.usertypes.DefaultValueIntegerType">
|
|
<param name="default">0</param>
|
|
</type>
|
|
</property>]]></programlisting>
|
|
|
|
<para>
|
|
Ahora el <literal>UserType</literal> puede recuperar el valor del parámetro
|
|
llamado <literal>default</literal> del objeto <literal>Properties</literal>
|
|
que se le pasa.
|
|
</para>
|
|
|
|
<para>
|
|
Si usas cierto <literal>UserType</literal> muy frecuentemente, puede ser útil
|
|
definir un nombre corto para é. Puedes hacer esto usando el elemento
|
|
<literal><typedef></literal>. Los typedefs asignan un nombre a un tipo
|
|
personalizado, y pueden también contener una lista de valores por defecto
|
|
de parámetros si el tipo fuese parametrizado.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
|
|
<param name="default">0</param>
|
|
</typedef>]]></programlisting>
|
|
|
|
<programlisting><![CDATA[<property name="priority" type="default_zero"/>]]></programlisting>
|
|
|
|
<para>
|
|
también es posible sobrescribir los parámetros provistos en un typedef sobre
|
|
una base caso por caso usando parámetros de tipo en el mapeo de la propiedad.
|
|
</para>
|
|
|
|
<para>
|
|
Aunque el rico espectro de tipos prefabricados y soporte de componentes de Hibernate
|
|
significa que raramente <emphasis>necesites</emphasis> usar un tipo personalizado;
|
|
sin embargo se considera una buena forma usar tipos personalizados para clases (no-entidades)
|
|
que aparezcan frecuentemente en tu aplicación. Por ejemplo, una clase
|
|
<literal>MonetaryAmount</literal> es una buena candidata para un
|
|
<literal>CompositeUserType</literal>, incluso cuando puede ser facilmente mapeada como un
|
|
componente. Un motivo para esto es la abstracción. Con un tipo personalizado,
|
|
tus documentos de mapeo estará impermeabilizados contra posibles cambios futuros en la
|
|
forma de representar valores monetarios.
|
|
</para>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="mapping-entityname">
|
|
<title>Mapeando una clase más de una vez</title>
|
|
<para>
|
|
Es posible proveer más de un mapeo para una clase persistente en particular. En este caso debes
|
|
especificar un <emphasis>nombre de entidad</emphasis> para desambiguar entr las instancias de las
|
|
dos entidades mapeadas. (Por defectom, el nombre de la entidad es el mismo que el nombre de la clase.)
|
|
Hibernate te deja especificar el nombre de entidad al trabajar con objetos persistentes, al escribir
|
|
consultas, o al mapear asociaciones a la entidad mencionada.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="Contract" table="Contracts"
|
|
entity-name="CurrentContract">
|
|
...
|
|
<set name="history" inverse="true"
|
|
order-by="effectiveEndDate desc">
|
|
<key column="currentContractId"/>
|
|
<one-to-many entity-name="HistoricalContract"/>
|
|
</set>
|
|
</class>
|
|
|
|
<class name="Contract" table="ContractHistory"
|
|
entity-name="HistoricalContract">
|
|
...
|
|
<many-to-one name="currentContract"
|
|
column="currentContractId"
|
|
entity-name="CurrentContract"/>
|
|
</class>]]></programlisting>
|
|
|
|
<para>
|
|
Observa cómo las asociaciones ahora se especifican usando <literal>entity-name</literal> en vez de
|
|
<literal>class</literal>.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="mapping-quotedidentifiers">
|
|
<title>identificadores SQL encomillados</title>
|
|
<para>
|
|
Puedes forzar a Hibernate a encomillar un identificador en el SQL generado encerrando el nombre
|
|
de tabla o columna entre backticks en el documento de mapeo. Hibernate usará el estilo de
|
|
encomillado para el <literal>Dialect</literal> SQL (usualmente comillas dobles, excepto corchetes
|
|
para SQL Server y backsticks para MySQL).
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<class name="LineItem" table="`Line Item`">
|
|
<id name="id" column="`Item Id`"/><generator class="assigned"/></id>
|
|
<property name="itemNumber" column="`Item #`"/>
|
|
...
|
|
</class>]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="mapping-alternatives">
|
|
<title>Alternativas de metadatos</title>
|
|
|
|
<para>
|
|
XML no es para todos, asá que hay algunas formas alternativas de definir metadatos de mapeo O/R
|
|
en Hibernate.
|
|
</para>
|
|
|
|
<sect2 id="mapping-xdoclet">
|
|
<title>Usando marcado de XDoclet</title>
|
|
|
|
<para>
|
|
Muchos usuarios de Hibernate prefieren embeber la información de mapeo directamente
|
|
en el código fuente usando las <literal>@hibernate.etiquetas</literal> XDoclet.
|
|
No cubriremos este enfoque en este documento, pues estrictamente es considerado parte
|
|
de XDoclet. Sin embargo, incluímos el siguiente ejemplo de la clase
|
|
<literal>Cat</literal> con mapeos XDoclet.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[package eg;
|
|
import java.util.Set;
|
|
import java.util.Date;
|
|
|
|
/**
|
|
* @hibernate.class
|
|
* table="CATS"
|
|
*/
|
|
public class Cat {
|
|
private Long id; // identifier
|
|
private Date birthdate;
|
|
private Cat mother;
|
|
private Set kittens
|
|
private Color color;
|
|
private char sex;
|
|
private float weight;
|
|
|
|
/*
|
|
* @hibernate.id
|
|
* generator-class="native"
|
|
* column="CAT_ID"
|
|
*/
|
|
public Long getId() {
|
|
return id;
|
|
}
|
|
private void setId(Long id) {
|
|
this.id=id;
|
|
}
|
|
|
|
/**
|
|
* @hibernate.many-to-one
|
|
* column="PARENT_ID"
|
|
*/
|
|
public Cat getMother() {
|
|
return mother;
|
|
}
|
|
void setMother(Cat mother) {
|
|
this.mother = mother;
|
|
}
|
|
|
|
/**
|
|
* @hibernate.property
|
|
* column="BIRTH_DATE"
|
|
*/
|
|
public Date getBirthdate() {
|
|
return birthdate;
|
|
}
|
|
void setBirthdate(Date date) {
|
|
birthdate = date;
|
|
}
|
|
/**
|
|
* @hibernate.property
|
|
* column="WEIGHT"
|
|
*/
|
|
public float getWeight() {
|
|
return weight;
|
|
}
|
|
void setWeight(float weight) {
|
|
this.weight = weight;
|
|
}
|
|
|
|
/**
|
|
* @hibernate.property
|
|
* column="COLOR"
|
|
* not-null="true"
|
|
*/
|
|
public Color getColor() {
|
|
return color;
|
|
}
|
|
void setColor(Color color) {
|
|
this.color = color;
|
|
}
|
|
/**
|
|
* @hibernate.set
|
|
* inverse="true"
|
|
* order-by="BIRTH_DATE"
|
|
* @hibernate.collection-key
|
|
* column="PARENT_ID"
|
|
* @hibernate.collection-one-to-many
|
|
*/
|
|
public Set getKittens() {
|
|
return kittens;
|
|
}
|
|
void setKittens(Set kittens) {
|
|
this.kittens = kittens;
|
|
}
|
|
// addKitten not needed by Hibernate
|
|
public void addKitten(Cat kitten) {
|
|
kittens.add(kitten);
|
|
}
|
|
|
|
/**
|
|
* @hibernate.property
|
|
* column="SEX"
|
|
* not-null="true"
|
|
* update="false"
|
|
*/
|
|
public char getSex() {
|
|
return sex;
|
|
}
|
|
void setSex(char sex) {
|
|
this.sex=sex;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>
|
|
Para más ejemplos de XDoclet e Hibernate ver en el sitio web de Hibernate.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="mapping-annotations" revision="2">
|
|
<title>Usando anotaciones JDK 5.0</title>
|
|
<para>
|
|
El JDK 5.0 introdujo anotaciones del estilo XDoclet a nivel del lenguaje,
|
|
con chequeo seguro de tipos en tiempo de compilación. Este mecanismo es más
|
|
potente y que las anotaciones XDoclet, y mejor soportado por herramientas e IDEs.
|
|
IntelliJ IDEA, por ejemplo, soporta auto-compleción y resaltado de sintaxis de anotaciones
|
|
JDK 5.0. La nueva revisión de la especificación de EJB (JSR-220) usa anotaciones
|
|
JDK 5.0 como el mecanismo primario de metadatos para beans de entidad. Hibernate3 implementa
|
|
el <literal>EntityManager</literal> del JSR-220 (la API de persistencia), y el soporte para
|
|
metadatos de mapeo está disponible vía el paquete <emphasis>Hibernate Annotations</emphasis>,
|
|
como una descarga por separado. Tanto metadatos de EJB3 (JSR-220) como de Hibernate3 están soportados.
|
|
</para>
|
|
|
|
<para>
|
|
Este es un ejemplo de una clase POJO anotada como un bean de entidad EJB:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[@Entity(access = AccessType.FIELD)
|
|
public class Customer implements Serializable {
|
|
|
|
@Id;
|
|
Long id;
|
|
|
|
String firstName;
|
|
String lastName;
|
|
Date birthday;
|
|
|
|
@Transient
|
|
Integer age;
|
|
|
|
@Embedded
|
|
private Address homeAddress;
|
|
|
|
@OneToMany(cascade=CascadeType.ALL)
|
|
|
|
@JoinColumn(name="CUSTOMER_ID")
|
|
Set<Order> orders;
|
|
|
|
// Getter/setter and business methods
|
|
}]]></programlisting>
|
|
|
|
<para>
|
|
Ten en cuenta que el soporte a anotaciones JDK 5.0 (y JSR-220) es todavía un
|
|
trabajo en progreso y no completado. Por favor, para más detalles refiérete al modulo
|
|
de Anotaciones de Hibernate.
|
|
</para>
|
|
|
|
</sect2>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
|
|
|
|
|