hibernate-orm/reference/es/modules/basic_mapping.xml
2005-06-13 12:04:11 +00:00

3223 lines
160 KiB
XML

<chapter id="mapping">
<title>Mapeo O/R B&#x00e1;sico</title>
<sect1 id="mapping-declaration" revision="1">
<title>Declaraci&#x00f3;n de mapeo</title>
<para>
Los mapeos objeto/relacional se definen usualmente en un documento XML.
El documento de mapeo est&#x00e1; dise&#x00f1;ado para ser le&#x00ed;ble y
editable a mano. El lenguaje de mapeo es Java-c&#x00e9;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&#x00f3;lo los
elementos y atributos que son usados por Hibernate en tiempo de ejecuci&#x00f3;n. El
documento de mapeo contiene adem&#x00e1;s algunos atributos y elementos extra opcionales
que afectan los esquemas de base de datos exportados por la herramienta de exportaci&#x00f3;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&#x00e1; el DTD primero en el classpath. Si experimentas
b&#x00fa;squedas del DTD usando una conexi&#x00f3;n de Internet, chequea tu declaraci&#x00f3;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&#x00e1;logo mencionado(s). De especificarse, los nombres de
tablas ser&#x00e1;n cualificados por el nombre de esquema y cat&#x00e1;logo dados.
De omitirse, los nombres de tablas no ser&#x00e1;n cualificados. El atributo
<literal>default-cascade</literal> especifica qu&#x00e9; 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&#x00e1;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&#x00f3;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&#x00f3;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&#x00e1; una excepci&#x00f3;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>&lt;class&gt;</literal> persistentes, como se muestra arriba.
Sin embargo, es una buena pr&#x00e1;ctica (y se espera de algunas herramientas) mapear
s&#x00f3;lo a una sola clase persistente (o a una sola jerarqu&#x00ed;a de clases) en
un fichero de mapeo y nombrarlo despu&#x00e9;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&#x00f3;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&#x00ed;z <literal>&lt;hibernate-mapping&gt;</literal>.
</para>
</callout>
<callout arearefs="class6">
<para>
<literal>catalog</literal> (opcional): Sobreescribe el nombre de cat&#x00e1;logo
especificado por el elemento ra&#x00ed;z <literal>&lt;hibernate-mapping&gt;</literal>.
</para>
</callout>
<callout arearefs="class7">
<para>
<literal>proxy</literal> (opcional): Especifica una interface a usar para proxies
de inicializaci&#x00f3;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&#x00f3;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&#x00f3;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&#x00f3;lo cuando un objeto transitorio ha sido asociado
con una sesi&#x00f3;n nueva usando <literal>update()</literal>), esto significa que Hibernate
realizar&#x00e1; 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&#x00ed;cito o expl&#x00ed;cito.
</para>
</callout>
<callout arearefs="class12">
<para>
<literal>where</literal> (opcional) especifica una condici&#x00f3;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&#x00f1;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&#x00f3;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&#x00ed;cito arbitrario para la entidad.
Para m&#x00e1;s informaci&#x00f3;n, mira
<xref linkend="persistent-classes-dynamicmodels"/> y <xref linkend="xml"/>.
</para>
</callout>
<callout arearefs="class18">
<para>
<literal>check</literal> (opcional): Una expresi&#x00f3;n SQL usada para generar
una restricci&#x00f3;n <emphasis>check</emphasis> multi-fila para la generaci&#x00f3;n
autom&#x00e1;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&#x00e1;pidas si estableces esta
opci&#x00f3;n a <literal>rowid</literal>. Un ROWID es un detalle de implementaci&#x00f3;n
y representa la posici&#x00f3;n f&#x00ed;sica de la tupla almacenada.
</para>
</callout>
<callout arearefs="class20">
<para>
<literal>subselect</literal> (opcional): Mapea una entidad inmutable y de s&#x00f3;lo
lectura a una subselect de base de datos. Es &#x00fa;til si quieres tener una vista
en vez de una tabla base, pero no tienes vistas. Mira debajo para m&#x00e1;s informaci&#x00f3;n.
</para>
</callout>
<callout arearefs="class21">
<para>
<literal>abstract</literal> (opcional): Usado para marcar superclases abstractas en
jerarqu&#x00ed;as <literal>&lt;union-subclass&gt;</literal>.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Es perfectamente aceptable que la clase persistente mencionada sea una interface.
Entonces declarar&#x00ed;as clases que implementan esa interface usando el elemento
<literal>&lt;subclass&gt;</literal>. Puedes persistir cualquier clase interna
<emphasis>est&#x00e1;tica</emphasis>. Debes especificar el nombre de la clase usando la forma
est&#x00e1;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&#x00f3;n. Esto permite a Hibernate hacer ciertas optimizaciones
menores de rendimiento.
</para>
<para>
El atributo opcional <literal>proxy</literal> habilita la inicializaci&#x00f3;n postergada
de instancias persistentes de la clase. Hibernate inicialmente retornar&#x00e1; proxies
CGLIB que implementan la interface mencionada. El objeto persistente real ser&#x00e1;
cargado cuando se invoque un m&#x00e9;todo del proxy. Mira "Proxies para Inicializaci&#x00f3;n
Postergada" debajo.
</para>
<para>
Por polimorfismo <emphasis>impl&#x00ed;cito</emphasis> se entiende que las instancias de la clase
ser&#x00e1;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&#x00e1;n devueltas
por una clase que mencione a la clase en s&#x00ed;.
Por polimorfismo <emphasis>expl&#x00ed;cito</emphasis> se entiende que instancias de la clase
ser&#x00e1;n devueltas s&#x00f3;lo por consultas que mencionen expl&#x00ed;citamente la clase;
y que las consultas que mencionen la clase devolver&#x00e1;n s&#x00f3;lo instancias de subclases
mapeadas dentro de esta declaraci&#x00f3;n <literal>&lt;class&gt;</literal> como una
<literal>&lt;subclass&gt;</literal> o <literal>&lt;joined-subclass&gt;</literal>.
Para la mayor&#x00ed;a de los prop&#x00f3;sitos el defecto,
<literal>polymorphism="implicit"</literal>, resulta apropiado.
El polimorfismo expl&#x00ed;cito es &#x00fa;til cuando dos clases diferentes est&#x00e1;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&#x00f3;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&#x00f3;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>&lt;subclass&gt;</literal> o <literal>&lt;joined-subclass&gt;</literal>.
Estos ajustes pueden incrementar el rendimiento en algunos casos, pero podr&#x00ed;an mermarlo en otros.
Ten juicio en su uso.
</para>
<para>
Generalmente el uso de <literal>select-before-update</literal> disminuir&#x00e1; el rendimiento.
Es muy &#x00fa;til prevenir que se llame innecesariamente a un disparador de actualizaci&#x00f3;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&#x00e1;s opci&#x00f3;n de estrategias
de bloqueo optimistas:
</para>
<itemizedlist>
<listitem>
<para>
<literal>version</literal> chequea las columnas de versi&#x00f3;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&#x00f3;n/timestamp para bloqueo optimista con Hibernate. Esta es la estrategia
&#x00f3;ptima con respecto al rendimiento y es la &#x00fa;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&#x00f3;lo lectura a una expresi&#x00f3;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>&lt;subselect&gt;</literal> est&#x00e1; 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&#x00ed;a de los casos tendr&#x00e1; tambi&#x00e9;n una propiedad
estilo Javabeans que tenga el identificador &#x00fa;nico de una instancia. El elemento
<literal>&lt;id&gt;</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&#x00e1;
reci&#x00e9;n instanciada (sin salvar), distingui&#x00e9;ndola de instancias separadas
que fueran salvadas o cargadas en una sesi&#x00f3;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&#x00f3;n <literal>&lt;composite-id&gt;</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>&lt;generator&gt;</literal> nombra una clase Java
usada en generar identificadores &#x00fa;nicos para instancias de la clase persistente.
De requerirse alg&#x00fa;n par&#x00e1;metro para configurar o inicializar la instancia del generador,
se pasa usando el elemento <literal>&lt;param&gt;</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&#x00f3;lo son &#x00fa;nicos cuando ning&#x00fa;n otro proceso
est&#x00e1; 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 &#x00fa;nicos s&#x00f3;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, &#x00fa;nicos en una ref (se usa la direcc&#x00f3;n IP). El UUID
se codifica como una cadena hexadecimal de 32 d&#x00ed;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&#x00f3;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>&lt;generator&gt;</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 &#x00fa;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&#x00f3;n
a una asociac&#x00f3;n de clave primaria <literal>&lt;uno-a-uno&gt;</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&#x00f3;n de identificadores.
La primera implementaci&#x00f3;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&#x00e1; 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&#x00f3;n IP, el instante de arranque de la JVM
(con una precisi&#x00f3;n de un cuarto de segundo), el tiempo de sistema y un valor
de contador (&#x00fa;nico en la JVM). No es posible obtener una direcci&#x00f3;n MAC o
una direcci&#x00f3;n de memoria desde c&#x00f3;digo Java, as&#x00ed; 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&#x00f3;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&#x00f3;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&#x00e1; 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&#x00f3;n asigne los identificadores (en contraposici&#x00f3;n
a que los genere Hibernate), puedes usar el generador <literal>assigned</literal>.
Este generador especial usar&#x00e1; 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>&lt;generator&gt;</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&#x00f3;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 &#x00e1;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&#x00fa;ltiples propiedades
de la clase como propiedades identificadoras. El elemento <literal>&lt;composite-id&gt;</literal>
acepta los mapeos de propiedad <literal>&lt;key-property&gt;</literal> y
los mapeos <literal>&lt;key-many-to-one&gt;</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&#x00e9;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&#x00e1;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&#x00e1;s conveniente donde el identificador
compuesto est&#x00e1; 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&#x00f3;n).
</para>
</listitem>
<listitem>
<para>
<literal>class</literal> (opcional - por defecto al tipo de la propiedad determinado
por reflecci&#x00f3;n): La clase del componente usado como identificador compuesto (ver siguiente secci&#x00f3;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&#x00e9;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>&lt;discriminator&gt;</literal> es requerido para la persistencia
polim&#x00f3;rfica usando la estrategia de mapeo de tabla-por-jerarqu&#x00ed;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&#x00e9; 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&#x00ed;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&#x00e9;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&#x00f3;n SQL arbitraria que
es ejecutada cuando un tipo tenga que ser evaluado. Permite dicriminaci&#x00f3;n
basada en el contenido.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Los valores reales de la columna discriminadora est&#x00e1;n especificados por
el atributo <literal>discriminator-value</literal> de los elementos
<literal>&lt;class&gt;</literal> y <literal>&lt;subclass&gt;</literal>.
</para>
<para>
El atributo <literal>force</literal> es (s&#x00f3;lo) &#x00fa;til si la tabla contiene
filas con valores discriminadores "extra" que no est&#x00e1;n mapeados a la clase
persistente. Generalmente este no es el caso.
</para>
<para>
Usando el atributo <literal>formula</literal> puedes declarar una expresi&#x00f3;n SQL
arbitraria que ser&#x00e1; 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>&lt;version&gt;</literal> es opcional e indica que la
tabla contiene datos versionados. Esto es particularmente &#x00fa;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&#x00fa;mero de versi&#x00f3;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&#x00fa;.mero de vesi&#x00f3;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&#x00f3;n que indica que una instancia est&#x00e1;
reci&#x00e9;n instanciada (sin guardar), distingui&#x00e9;ndola de instancias
separadas que fueran guardadas o cargadas en una sesi&#x00f3;n previa.
(<literal>undefined</literal> especifica que debe usarse el valor de la
propiedad identificadora.)
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Los n&#x00fa;meros de versi&#x00f3;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&#x00f3;n o timestamp nunca debe ser nula para una instancia
separada, de modo que Hibernate detectar&#x00e1; cualquier instancia con una versi&#x00f3;n
o timestamp nulo como transitoria, sin importar qu&#x00e9; otras estrategias
<literal>unsaved-value</literal> se hayan especificado.
<emphasis>Declarar una propiedad de vers&#x00f3;n o timestamp nulable es una forma
f&#x00e1;cil de evitar cualquier problema con la re-uni&#x00f3;n transitiva en Hibernate,
especialmente &#x00fa;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>&lt;timestamp&gt;</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&#x00f3;n menos
segura de bloqueo optimista. Sin embrago, a veces la aplicaci&#x00f3;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&#x00f3;n que indica que una instancia est&#x00e1;
reci&#x00e9;n instanciada (sin guardar), distingui&#x00e9;ndola de instancias separadas
que hayan sido guardadas o cargadas en una sesi&#x00f3;n previa.
(<literal>undefined</literal> especifica que debe usarse el valor de la propiedad
identificadora.)
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Note that <literal>&lt;timestamp&gt;</literal> is equivalent to
<literal>&lt;version type="timestamp"&gt;</literal>.
</para>
</sect2>
<sect2 id="mapping-declaration-property" revision="2">
<title>property</title>
<para>
El elemento <literal>&lt;property&gt;</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&#x00fa;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&#x00e9;n ser especificado
con elemento(s) <literal>&lt;column&gt;</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&#x00ed;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&#x00f3;n.
</para>
</callout>
<callout arearefs="property6">
<para>
<literal>formula</literal> (opcional): una expresi&#x00f3;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&#x00ed;da perezosamente cuando la variable de instancia
sea accedida por primera vez (requiere instrumentaci&#x00f3;n en tiempo de compilaci&#x00f3;n).
</para>
</callout>
<callout arearefs="property9">
<para>
<literal>unique</literal> (opcional): Habilita la generaci&#x00f3; DDL de una restricci&#x00f3;n
de unicidad para las columnas. Adem&#x00e1;s, permite que &#x00e9;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&#x00f3; DDL de una restricci&#x00f3;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&#x000f3;n
de un bloqueo optimista. En otras palabras, determina si debe ocurrir un incremento de versi&#x00f3;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&#x00e1;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&#x00e1;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&#x00e1; reflecci&#x00f3;n sobre la
propiedad mencionada para deducir el tipo Hibernate correcto. Hibernate intentar&#x00e1;
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&#x00e1;s
a&#x00fa;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&#x00f3;mo Hibernate
acceder&#x00e1; a la propiedad en tiempo de ejecuci&#x00f3;n. Por defecto, Hibernate
llamar&#x00e1; al par de getter/setter de la propiedad. Si especificas
<literal>access="field"</literal>, Hibernate se saltar&#x00e1; el par get/set y
acceder&#x00e1; al campo directamente usando reflecci&#x00f3;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&#x00f3;n de s&#x00f3;lo lectura, el valor de la propiedad es computado
en tiempo de carga. Tu declaras la computaci&#x00f3;n como una expresi&#x00f3;n SQL,
y &#x00e9;sta se traduce a cl&#x00e1;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&#x00e1;s que puedes usar el elemento anidado de mapeo <literal>&lt;formula&gt;</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&#x00f3;n ordinaria a otra clase persistente se declara usando
el elemento <literal>many-to-one</literal>. El modelo relacional es una
asociaci&#x00f3;n muchos-a-uno: una clave for&#x00e1;nea en una tabla est&#x00e1;
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&#x00f3;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&#x00e1;nea.
Tambi&#x00e9;n puede ser especificado por uno o varios elementos anidados
<literal>&lt;column&gt;</literal>.
</para>
</callout>
<callout arearefs="manytoone3">
<para>
<literal>class</literal> (opcional - por defecto al tipo de la propiedad
determinado por reflecci&#x00f3;n): El nombre de la clase asociada.
</para>
</callout>
<callout arearefs="manytoone4">
<para>
<literal>cascade</literal> (opcional): Especifica qu&#x00e9; 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&#x00f3;n outer-join o por selecci&#x00f3;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&#x00ed;das en las sentencias SQL
<literal>UPDATE</literal> y/o <literal>INSERT</literal>. Establecer ambas a
<literal>false</literal> permite una asociaci&#x00f3;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&#x00f3;n.
</para>
</callout>
<callout arearefs="manytoone8">
<para>
<literal>property-ref</literal>: (opcional) El nombre de la propiedad de la clase
asociada que est&#x00e1; unida a la clave for&#x00e1;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&#x00f3;n DDL de una
restricci&#x00f3;n de unicidad para la columna de clave for&#x00e1;nea. Adem&#x00e1;s,
permite que &#x00e9;sta sea el objetivo de una <literal>property-ref</literal>.
Esto hace efectivamente la multiplicidad de la asociaci&#x00f3;n uno a uno.
</para>
</callout>
<callout arearefs="manytoone11">
<para>
<literal>not-null</literal> (opcional): Habilita la generaci&#x00f3;n DDL de una
restricci&#x00f3;n de nulabilidad para las columnas de clave for&#x00e1;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&#x00f3;n
del bloqueo optimista. En otras palabras, determina si debe darse un incremento de versi&#x00f3;n
cuando esta propiedad est&#x00e9; desactualizada.
</para>
</callout>
<callout arearefs="manytoone13">
<para>
<literal>lazy</literal> (opcional - por defecto a <literal>proxy</literal>):
Por defecto, las asociaciones de punto &#x00fa;nico van con proxies.
<literal>lazy="true"</literal> especifica que esta propiedad debe ser
tra&#x00ed;da perezosamente cuando la variable de instancia sea accedida por primera
vez (requiere instrumentaci&#x00f3;n del bytecode en tiempo de compilaci&#x00f3;n).
<literal>lazy="false"</literal> especifica que la asociaci&#x00f3;n siempre ser&#x00e1;
recuperada tempranamente.
</para>
</callout>
<callout arearefs="manytoone14">
<para>
<literal>not-found</literal> (opcional - por defecto a <literal>exception</literal>):
Especifica c&#x00f3;mo deben manejarse las claves for&#x00e1;neas que referencien
filas inexistentes: <literal>ignore</literal> tratar&#x00e1; una fila perdida como
una asociaci&#x00f3;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&#x00f3;n SQL que define el valor
para una clave for&#x00e1;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&#x00e1; ciertas
operaciones al objeto asociado. Los valores significativos son los nombres de las
operaciones b&#x00e1;sicas de Hibernate, <literal>persist, merge, delete, save-update,
evict, replicate, lock, refresh</literal>, as&#x00ed; 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&#x00f3;n completa,
ver <xref linkend="objectstate-transitive"/>.
</para>
<para>
Una declaraci&#x00f3;n t&#x00ed;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&#x00e1;nea referencia una clave &#x00fa;nica de
la tabla asociada, distinta de la clave primaria. Este es un modelo relacional feo.
Por ejemplo, sup&#x00f3;n que la clase <literal>Product</literal> tuviera un n&#x00fa;mero
&#x00fa;nico serial que no es la clave primaria. (El atributo <literal>unique</literal>
controla la generaci&#x00f3;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&#x00ed;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 &#x00fa;nica referenciada abarca m&#x00fa;ltiples propiedades de la entidad asociada,
debes mapear las propiedades dentro de un elemento <literal>&lt;properties&gt;</literal>.
</para>
</sect2>
<sect2 id="mapping-declaration-onetoone" revision="2">
<title>one-to-one</title>
<para>
Una asociaci&#x00f3;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&#x00f3;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&#x00f3;n): El nombre de la clase asociada.
</para>
</callout>
<callout arearefs="onetoone3">
<para>
<literal>cascade</literal> (opcional) especifica qu&#x00e9; 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&#x00f3;n
de clave for&#x00e1;nea de la tabla mapeada referencia a la tabla de la clase
asociada. Esta opci&#x00f3;n afecta el orden en que van en cascada
<literal>save()</literal> y <literal>delete()</literal>, y determina cu&#x00e1;ndo
la asociaci&#x00f3;n pueden ser virtualizados por proxies (es tambi&#x00e9;n usado por
la herramienta de exportaci&#x00f3;n de esquemas).
</para>
</callout>
<callout arearefs="onetoone5">
<para>
<literal>fetch</literal> (opcional - por defecto <literal>select</literal>):
Elige entre recuperaci&#x00f3;n outer-join o recuperaci&#x00f3;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&#x00e9; 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&#x00f3;n para unir usando una
f&#x00f3;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 &#x00fa;nico van con proxies.
<literal>lazy="true"</literal> especifica que esta propiedad debe ser
tra&#x00ed;da perezosamente cuando la variable de instancia sea accedida por primera
vez (requiere instrumentaci&#x00f3;n del bytecode en tiempo de compilaci&#x00f3;n).
<literal>lazy="false"</literal> especifica que la asociaci&#x00f3;n siempre ser&#x00e1;
recuperada tempranamente. <emphasis>Observa que si <literal>constrained="false"</literal>,
la aplicaci&#x00f3;n de proxies es imposible e Hibernate traer&#x00e1; temprano la
asociaci&#x00f3;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&#x00e1;neas &#x00fa;nica
</para></listitem>
</itemizedlist>
<para>
Las asociaciones de clave primaria no necesitan una columna de tabla extra; si dos filas
est&#x00e1;n relacionadas por la asociaci&#x00f3;n entonces las dos filas de tablas comparten
el mismo valor de clave primaria. Por lo tanto, si quieres que dos objetos est&#x00e9;n relacionados
por una asociaci&#x00f3;n de clave primaria, debes asegurarte que se les asigne el mismo valor de
identificador!
</para>
<para>
Para una asociaci&#x00f3;n de clave primaria, a&#x00f1;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&#x00f3;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&#x00e9;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&#x00e1;nea con una restricci&#x00f3;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&#x00f3;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&#x00ed;a debes
intentar identificar claves naturales para todas las entidades. Una clave natural es una
propiedad o combinaci&#x00f3;n de propiedades que es &#x00fa;nica y no nula. Si adem&#x00e1;s
es inmutable, mejor a&#x00fa;n. Mapea las propiedades de la clave natural dentro del elemento
<literal>&lt;natural-id&gt;</literal>. Hibernate generar&#x00e1; las restricciones de clave
&#x00fa;nica y nulabilidad necesarias, y tu mapeo ser&#x00e1; m&#x00e1;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&#x00e1; 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>&lt;component&gt;</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&#x00f3;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&#x00f3;n de bytecode en tiempo de
compilaci&#x00f3;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&#x00f3;n de un bloqueo optimista. En otras palabras, determina si
debe ocurrir un incremento de versi&#x00f3;n cuando esta propiedad est&#x00e1;
desactualizada.
</para>
</callout>
<callout arearefs="component8">
<para>
<literal>unique</literal> (opcional - por defecto a <literal>false</literal>):
Especifica que existe una restricci&#x00f3;n de unicidad sobre todas las
columnas mapeadas del componente.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Las etiquetas hijas <literal>&lt;property&gt;</literal> mapean propiedades de la
clase hija columnas de la tabla.
</para>
<para>
El elemento <literal>&lt;component&gt;</literal> permite un subelemento
<literal>&lt;parent&gt;</literal> que mapea una propiedad de la clase del componente
como una referencia de regreso a la entidad contenedora.
</para>
<para>
El elemento <literal>&lt;dynamic-component&gt;</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>&lt;properties&gt;</literal> permite la definici&#x00f3;n de
un grupo de propiedades l&#x00f3;gico con nombre de una clase. El uso m&#x00e1;s
importante de la contrucci&#x00f3;n es que permite que una combinaci&#x00f3;n
de propiedades sea objetivo de una <literal>property-ref</literal>. Es tambi&#x00e9;n
una forma conveniente de definir una restricci&#x00f3;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&#x00f3;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&#x00f3;n de un bloqueo optimista. En otras palabras, determina si
debe ocurrir un incremento de versi&#x00f3;n cuando estas propiedades est&#x00e1;n
desactualizadas.
</para>
</callout>
<callout arearefs="properties5">
<para>
<literal>unique</literal> (opcional - por defecto a <literal>false</literal>):
Especifica que existe una restricci&#x00f3;n de unicidad sobre todas las
columnas mapeadas del componente.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Por ejemplo, si tenemos el siguiente mapeo de <literal>&lt;properties&gt;</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&#x00f3;n de datos heredados que se refiera
a esta clave &#x00fa;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&#x00f3;rfica requiere la declaraci&#x00f3;n
de la clase persistente ra&#x00ed;z. Para la estrategia de mapeo
tabla-por-jerarqu&#x00ed;a-de-clases, se usa la declaraci&#x00f3;n de
<literal>&lt;subclass&gt;</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&#x00f3;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&#x00f3;n
perezosa.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Cada subclase debe declarar sus propias propiedades persistentes y subclases.
Se asume que las propiedades <literal>&lt;version&gt;</literal> y <literal>&lt;id&gt;</literal>
son heredadas de la clase ra&#x00ed;z. Cada subclase en una jerarqu&#x00ed;a debe
definir un <literal>discriminator-value</literal> &#x00fa;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&#x00ed;a de clases
con s&#x00f3;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&#x00ed;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&#x00ed;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&#x00f3;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>&lt;joined-subclass&gt;</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&#x00f3;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&#x00f3;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>&lt;key&gt;</literal>. El mapeo del comienzo del cap&#x00ed;tulo
deber&#x00ed;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&#x00f3;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&#x00f3;n es mapear s&#x00f3;lo las clases concretas de una
jerarqu&#x00ed;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&#x00ed;as de herencia. Puedes simplemente mapear cada clase con una
declaraci&#x00f3;n <literal>&lt;class&gt;</literal> separada. Sin embargo,
si deseas usar asociaciones polim&#x00f3;rficas (por ejemplo, una asociaci&#x00f3;n
a la superclase de tu jerarqu&#x00ed;a), debes usar el mapeo
<literal>&lt;union-subclass&gt;</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&#x00f3;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&#x00f3;n
perezosa.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
No se requiere columna o columna clave discriminadora para esta estrategia de mapeo.
</para>
<para>
Para informaci&#x00f3;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>&lt;join&gt;</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&#x00ed;z <literal>&lt;hibernate-mapping&gt;</literal>.
</para>
</callout>
<callout arearefs="join3">
<para>
<literal>catalog</literal> (opcional): Sobrescribe el nombre de cat&#x00e1;logo
especificado por el elemento ra&#x00ed;z <literal>&lt;hibernate-mapping&gt;</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&#x00e1;
una uni&#x00f3;n interior (inner join) para recuperar un <literal>&lt;join&gt;</literal>
definido por una clase o sus superclases y una uni&#x00f3;n externa (outer join)
para un <literal>&lt;join&gt;</literal> definido por una subclase.
Si se establece a <literal>select</literal>, entonces Hibernate usar&#x00e1; una
select secuencial para un <literal>&lt;join&gt;</literal> definido en una subclase,
que ser&#x00e1; publicada s&#x00f3;lo si una fila resulta representar una instancia
de la subclase. Las uniones interiores todav&#x00ed;a ser&#x00e1;n usados para
recuperar un <literal>&lt;join&gt;</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&#x00e1; insertar o actualizar las propiedades
definidas por esta uni&#x00f3;n.
</para>
</callout>
<callout arearefs="join6">
<para>
<literal>optional</literal> (opcional - por defecto a <literal>false</literal>):
De habilitarse, Hibernate insertar&#x00e1; una fila s&#x00f3;lo si las propiedades
definidas por esta uni&#x00f3;n son no nulas y siempre usar&#x00e1; una uni&#x00f3;n
externa para recuperar las propiedades.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Por ejemplo, la informaci&#x00f3;n domiciliaria de una persona puede ser mapeada
a una tabla separada (preservando a la vez la sem&#x00e1;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 &#x00fa;til para modelos de datos
heredados; recomendamos menos tablas que clases un modelo de dominio m&#x00e1;s
granularizado. Sin embargo, es &#x00fa;til para cambiar entre estrategias de mapeo
de herencias en una misma jerarqu&#x00ed;a, como se explica luego.
</para>
</sect2>
<sect2 id="mapping-declaration-key">
<title>key</title>
<para>
Hasta ahora hemos visto el elemento <literal>&lt;key&gt;</literal> pocas veces.
Aparece en cualquier sitio en que el elemento padre de mapeo defina una uni&#x00f3;n
a una nueva tabla, y define la clave for&#x00e1;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&#x00e1;nea.
Puede ser tambi&#x00e9;n especificado por elemento(s) anidado(s)
<literal>&lt;column&gt;</literal>.
</para>
</callout>
<callout arearefs="key2">
<para>
<literal>on-delete</literal> (opcional, por defecto a <literal>noaction</literal>):
Especifica si la restricci&#x00f3;n de clave for&#x00e1;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&#x00e1;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&#x00e1;nea son no nulables (esto est&#x00e1; implicado si la clave for&#x00e1;nea
es tambi&#x00e9;n parte de la clave primaria).
</para>
</callout>
<callout arearefs="key5">
<para>
<literal>update</literal> (opcional): Especifica que la clave for&#x00e1;nea nunca
debe ser actualizada (esto est&#x00e1; implicado si la clave for&#x00e1;nea
es tambi&#x00e9;n parte de la clave primaria).
</para>
</callout>
<callout arearefs="key6">
<para>
<literal>unique</literal> (opcional): Especifica que la clave for&#x00e1;nea
debe tener una restricci&#x00f3;n de unicidad (esto est&#x00e1; implicado si
la clave for&#x00e1;nea es tambi&#x00e9;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&#x00e1;
una restricci&#x00f3;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 &#x00fa;tiles
al mapear una asociaci&#x00f3;n uno a muchos unidireccional. Si mapeas una uno a muchos
unidireccional a una clave for&#x00e1;nea no nulable, <emphasis>debes</emphasis> declarar
la columna clave usando <literal>&lt;key not-null="true"&gt;</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&#x00e1;
alternativamente un subelemento <literal>&lt;column&gt;</literal>. De forma similar,
<literal>&lt;formula&gt;</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&#x00f3;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&#x00f3;n para
expresar, por ejemplo, condiciones de uni&#x00f3;n ex&#x00f3;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&#x00f3;n que tu aplicaci&#x00f3;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&#x00ed;citamente, en vez de confiar en
<literal>auto-import="true"</literal>. Puedes incluso importar clases e interfaces que
no est&#x00e9;n mapeadas expl&#x00ed;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&#x00e1; 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&#x00e1;s de mapeo de propiedad. El elemento de mapeo <literal>&lt;any&gt;</literal>
define una asociaci&#x00e1;n polim&#x00f3;rfica a clases desde m&#x00fa;ltiples tablas. Este tipo
de mapeo siempre requiere m&#x00e1;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&#x00f3;n de clave for&#x00e1;nea para este tipo de asociaci&#x00f3;n, por lo que
esto ciertamente no est&#x00e1; concebido como la forma habitual de mapear asociaciones
(polim&#x00f3;rficas). S&#x00f3;lo debes usar esto en casos muy especiales (por ejemplo,
trazas de auditor&#x00e9;a, datos de sesi&#x00f3;n de usuario, etc).
</para>
<para>
El atributo <literal>meta-type</literal> permite a la aplicaci&#x00f3;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&#x00f3;n del bloqueo optimista. En otras palabras, determina si debe ocurrir
un incremento de versi&#x00f3;n cuando esta propiedad est&#x00e1; 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&#x00ed;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&#x00e1;s de cerca a c&#x00f3;mo los objetos de aplicaci&#x00f3;n son usados
habitualmente en grandes sistemas. Las entidades soportan referencias circulares y
compartidas, que tambi&#x00e9; 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&#x00e1; dentro de la colecci&#x00f3;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&#x00e9;rmino "clase persistente"
para referirnos a entidades. Continuaremos haci&#x00e9;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&#x00e1;ntica de valor.
Una propiedad Java de tipo <literal>java.lang.String</literal> tambi&#x00e9;n
tiene sem&#x00e1;ntica de valor. Dada esta definici&#x00f3;n, podemos decir
que todos los tipo (clases) provistos por el JDK tienen una sem&#x00e1;ntica
de tipo valor en Java, mientras que los tipos definidos por el usuario
pueden ser mapeados con sem&#x00e1;ntica de tipo valor o de entidad.
La desici&#x00f3;n corre por cuenta del desarrollador de la aplicaci&#x00f3;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&#x00f3;n
o agregaci&#x00f3;n usualmente se traducen a un tipo de valor.
</para>
<para>
Volveremos a visitar ambos conceptos a lo largo de la documentaci&#x00f3;n.
</para>
<para>
EL desaf&#x00ed;o es mapear el sistema de tipos de Java (y la definici&#x00f3;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>&lt;class&gt;</literal>,
<literal>&lt;subclass&gt;</literal>, etc. Para los tipos de valor usamos
<literal>&lt;property&gt;</literal>, <literal>&lt;component&gt;</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&#x00e1;brica muchos mapeos (para tipos de valores del JDK
est&#x00e1;ndar). Puedes escribir tus propios mapeos de tipo, as&#x00ed; como
implementar tus estrategias de conversi&#x00f3;n personalizadas, como veremos luego.
</para>
<para>
Todos los tipos prefabricados de Hibernate soportan sem&#x00e1;ntica de nulos
excepto las colecciones.
</para>
</sect2>
<sect2 id="mapping-types-basictypes" revision="2">
<title>Tipos de valores b&#x00e1;sicos</title>
<para>
Los <emphasis>tipos de mapeo b&#x00e1;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&#x00ed;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&#x00f3;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&#x00e1;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&#x00e1;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&#x00f3;n (Adem&#x00e1;s, el soporte del driver suele
ser malo e inconsistente).
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Los identificadores &#x00fa;nicos de entidades y collecciones pueden ser de cualquier
tipo b&#x00e1;sico excepto <literal>binary</literal>, <literal>blob</literal>
y <literal>clob</literal>.
(Los identificadores compuestos est&#x00e1;n tambi&#x00e9;n permitidos, ver debajo.)
</para>
<para>
Los tipos de valor b&#x00e1;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&#x00e1;cil para los desarrolladores crear sus propios tipos de valor.
Por ejemplo, podr&#x00ed;as querer persistir propiedades del tipo <literal>java.lang.BigInteger</literal>
a columnas <literal>VARCHAR</literal>. Hibernate no provee un tipo de f&#x00e1;brica para esto.
Pero los tipos personalizados no est&#x00e1;n limitados a mapear una propiedad (o elemento de colecci&#x00f3;n)
a una sola columna de tabla. As&#x00ed;, por ejemplo, podr&#x00ed;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&#x00e9; 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>&lt;column&gt;</literal> para mapear una propiedad
a m&#x00fa;ltiples columnas.
</para>
<para>
Las interfaces <literal>CompositeUserType</literal>, <literal>EnhancedUserType</literal>,
<literal>UserCollectionType</literal>, y <literal>UserVersionType</literal> proveen
soporte a usos m&#x00e1;s especializados.
</para>
<para>
Puedes incluso proveer de par&#x00e1;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&#x00e1;metros a tu tipo personalizado, puedes usar el elemento
<literal>&lt;type&gt;</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&#x00e1;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 &#x00fa;til
definir un nombre corto para &#x00e9;. Puedes hacer esto usando el elemento
<literal>&lt;typedef&gt;</literal>. Los typedefs asignan un nombre a un tipo
personalizado, y pueden tambi&#x00e9;n contener una lista de valores por defecto
de par&#x00e1;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&#x00e9;n es posible sobrescribir los par&#x00e1;metros provistos en un typedef sobre
una base caso por caso usando par&#x00e1;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&#x00f3;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&#x00f3;n. Con un tipo personalizado,
tus documentos de mapeo estar&#x00e1; impermeabilizados contra posibles cambios futuros en la
forma de representar valores monetarios.
</para>
</sect2>
</sect1>
<sect1 id="mapping-entityname">
<title>Mapeando una clase m&#x00e1;s de una vez</title>
<para>
Es posible proveer m&#x00e1;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&#x00f3;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&#x00e1; 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&#x00e1; 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&#x00f3;n de mapeo directamente
en el c&#x00f3;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&#x00ed;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&#x00e1;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&#x00f3;n. Este mecanismo es m&#x00e1;s
potente y que las anotaciones XDoclet, y mejor soportado por herramientas e IDEs.
IntelliJ IDEA, por ejemplo, soporta auto-compleci&#x00f3;n y resaltado de sintaxis de anotaciones
JDK 5.0. La nueva revisi&#x00f3;n de la especificaci&#x00f3;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&#x00e1; disponible v&#x00ed;a el paquete <emphasis>Hibernate Annotations</emphasis>,
como una descarga por separado. Tanto metadatos de EJB3 (JSR-220) como de Hibernate3 est&#x00e1;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&#x00ed;a un
trabajo en progreso y no completado. Por favor, para m&#x00e1;s detalles refi&#x00e9;rete al modulo
de Anotaciones de Hibernate.
</para>
</sect2>
</sect1>
</chapter>