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

528 lines
17 KiB
XML

<chapter id="associations">
<title>Mapeos de Asociaci&#x00f3;n</title>
<sect1 id="assoc-intro" revision="1">
<title>Introducci&#x00f3;n</title>
<para>
Los mapeos de asociaci&#x00f3;n son frecuentemente las cosas mas dif&#x00ed;ciles
de hacer correctamente. En esta secci&#x00f3;n iremos a trav&#x00e9;s de los casos
can&#x00f3;nicos uno a uno, comenzando con los mapeos unidireccionales, y considerando
luego los casos bidireccionales. Usaremos <literal>Person</literal> y <literal>Address</literal>
en todos los ejemplos.
</para>
<para>
Clasificaremos las asociaciones por cuanto mapeen o no a una tabla
de uni&#x00f3;n interviniente, y por su multiplicidad.
</para>
<para>
Las claves for&#x00e1;neas que aceptan valores nulos (en adelante, nullables)
no son consideradas una buena pr&#x00e1;ctica en el modelado tradicional de datos,
as&#x00ed; que todos nuestros ejemplos usan claves for&#x00e1;neas no nullables.
Esto no es un requerimiento de Hibernate, y todos los mapeos funcionar&#x00e1;n
si quitas las restricciones de nulabilidad.
</para>
</sect1>
<sect1 id="assoc-unidirectional" revision="1">
<title>Asociaciones Unidireccionales</title>
<sect2 id="assoc-unidirectional-m21">
<title>muchos a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional muchos-a-uno</emphasis> es el tipo
m&#x00e1;s com&#x00fa;n de asociaciones unidireccionales.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-unidirectional-121">
<title>uno a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional uno-a-uno en una clave primaria</emphasis>
es casi id&#x00e9;ntica. La &#x00fa;nica diferencia es la restricci&#x00f3;n de unicidad
de la columna.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
<para>
Usualmente, una <emphasis>asociaci&#x00f3;n unidireccional uno-a-uno en una
clave primaria</emphasis> usa un generador de id especial. (Observa que hemos
invertido el sentido de la asociaci&#x00f3;n en este ejemplo).
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
</class>
<class name="Address">
<id name="id" column="personId">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<one-to-one name="person" constrained="true"/>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-unidirectional-12m">
<title>uno a muchos</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional uno-a-muchos en una clave for&#x00e1;nea</emphasis>
es un caso muy inusual, y realmente no est&#x00e1; recomendada.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses">
<key column="personId"
not-null="true"/>
<one-to-many class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not null )
]]></programlisting>
<para>
Creemos que es mejor usar una tabla de uni&#x00f3;n para este tipo de asociaci&#x00f3;n.
</para>
</sect2>
</sect1>
<sect1 id="assoc-unidirectional-join" revision="1">
<title>Asociaciones unidireccionales con tablas de uni&#x00f3;n</title>
<sect2 id="assoc-unidirectional-join-12m">
<title>uno a muchos</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional uno-a-muchos en una tabla de uni&#x00f3;n</emphasis>
es m&#x00e1;s preferible. Observa que especificando <literal>unique="true"</literal>, hemos
cambiado la multiplicidad de muchos-a-muchos a uno-a-muchos.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
unique="true"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-unidirectional-join-m21">
<title>muchos a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional muchos-a-uno en una tabla de uni&#x00f3;n</emphasis>
es bastante com&#x00fa;n cuando la asociaci&#x00f3;n es opcional.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId" unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-unidirectional-join-121">
<title>uno a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n unidireccional uno-a-uno en una tabla de uni&#x00f3;n</emphasis>
es inusual en extremo, pero posible.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId"
unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"
unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-unidirectional-join-m2m">
<title>muchos a muchos</title>
<para>
Finalmente, tenemos una <emphasis>asociaci&#x00f3;n unidireccional muchos-a-muchos</emphasis>
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
</sect1>
<sect1 id="assoc-bidirectional" revision="1">
<title>Asociaciones Bidireccionales</title>
<sect2 id="assoc-bidirectional-m21">
<title>uno a muchos / muchos a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n bidireccional muchos-a-uno</emphasis> es
el tipo m&#x00e1;s com&#x00fa;n de asociaci&#x00f3;n. (Esta es la relaci&#x00f3;n
est&#x00e1;ndar padre/hijo.)
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true">
<key column="addressId"/>
<one-to-many class="Person"/>
</set>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-bidirectional-121">
<title>uno a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n bidireccional uno-a-uno en una clave for&#x00e1;nea</emphasis>
es bastante com&#x00fa;n.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
unique="true"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<one-to-one name="person"
property-ref="address"/>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
<para>
Una <emphasis>asociaci&#x00f3;n bidireccional uno-a-uno en una clave primaria</emphasis>
usa el generador de id especial.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<one-to-one name="address"/>
</class>
<class name="Address">
<id name="id" column="personId">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<one-to-one name="person"
constrained="true"/>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
]]></programlisting>
</sect2>
</sect1>
<sect1 id="assoc-bidirectional-join" revision="1">
<title>Asociaciones bidireccionales con tablas de uni&#x00f3;n</title>
<sect2 id="assoc-bidirectional-join-12m">
<title>uno a muchos / muchos a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n bidireccional uno-a-muchos en una tabla de uni&#x00f3;n</emphasis>.
Observa que el <literal>inverse="true"</literal> puede ir a cualquier lado de la asociaci&#x00f3;n,
en la colecci&#x00f3;n, o en la uni&#x00f3;n.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses"
table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
unique="true"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<join table="PersonAddress"
inverse="true"
optional="true">
<key column="addressId"/>
<many-to-one name="person"
column="personId"
not-null="true"/>
</join>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null primary key )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-bidirectional-join-121">
<title>uno a uno</title>
<para>
Una <emphasis>asociaci&#x00f3;n bidireccional uno-a-uno en una tabla de uni&#x00f3;n</emphasis>
es inusual en extremo, pero posible.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true">
<key column="personId"
unique="true"/>
<many-to-one name="address"
column="addressId"
not-null="true"
unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<join table="PersonAddress"
optional="true"
inverse="true">
<key column="addressId"
unique="true"/>
<many-to-one name="address"
column="personId"
not-null="true"
unique="true"/>
</join>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
<sect2 id="assoc-bidirectional-join-m2m">
<title>muchos a muchos</title>
<para>
Finalmente, tenemos una <emphasis>asociaci&#x00f3;n bidireccional muchos-a-muchos</emphasis>.
</para>
<programlisting><![CDATA[<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<set name="addresses">
<key column="personId"/>
<many-to-many column="addressId"
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true">
<key column="addressId"/>
<many-to-many column="personId"
class="Person"/>
</set>
</class>]]></programlisting>
<programlisting><![CDATA[
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )
]]></programlisting>
</sect2>
</sect1>
</chapter>