|
You have a 1-N (one to many) or N-1 (many to one) when you have one object of a class that has a Map of
objects of another class. There are two general ways in which you can represent this in a datastore.
Join Table
(where a join table is used to provide the relationship mapping between the objects), and
Foreign-Key
(where a foreign key is placed in the table of the object contained in the Map. JPA
only supports the Foreign-Key approach where you have the key stored as a field in the value.
The various possible relationships are described below.
This page is aimed at Map fields and so applies to fields of Java type
java.util.HashMap, java.util.Hashtable, java.util.LinkedHashMap, java.util.Map, java.util.SortedMap,
java.util.TreeMap, java.util.Properties
In this case we have an object with a Map of objects and we're associating the objects using a
foreign-key in the table of the value. We're using a field (
alias
) in the Address class as
the key of the map.
In this relationship, the
Account
class has a Map of
Address
objects, yet the
Address
knows nothing about the
Account
. In this case we don't have a field in the
Address to link back to the Account and so DataNucleus has to use columns in the datastore representation of
the
Address
class. So we define the MetaData like this
<entity-mappings>
<entity class="Account">
<table name="ACCOUNT"/>
<attributes>
<id name="id">
<column name="ACCOUNT_ID"/>
</id>
...
<one-to-many name="addresses" target-entity="com.mydomain.Address">
<map-key name="alias"/>
<join-column name="ACCOUNT_ID_OID"/>
</one-to-many>
</attributes>
</entity>
<entity class="Address">
<table name="ADDRESS"/>
<attributes>
<id name="id">
<column name="ADDRESS_ID"/>
</id>
...
<basic name="alias">
<column name="KEY" length="20"/>
</basic>
</attributes>
</entity>
</entity-mappings>
Again there will be 2 tables, one for
Address
, and one for
Account
.
If you wish to specify the names of the columns used in the schema for the foreign key in the
Address
table you should use the
join-column
element within the field of the map.
In terms of operation within your classes of assigning the objects in the relationship. You have to
take your
Account
object and add the
Address
to the
Account
map field since the
Address
knows nothing about the
Account
. Also be aware that each
Address
object
can have only one owner, since it has a single foreign key to the
Account
.
In this case we have an object with a Map of objects and we're associating the objects using a
foreign-key in the table of the value.
With these classes we want to store a foreign-key in the value table (ADDRESS), and we want to use the "alias"
field in the Address class as the key to the map. If you define the Meta-Data for these classes as follows
<entity-mappings>
<entity class="Account">
<table name="ACCOUNT"/>
<attributes>
<id name="id">
<column name="ACCOUNT_ID"/>
</id>
...
<one-to-many name="addresses" target-entity="com.mydomain.Address" mapped-by="account">
<map-key name="alias"/>
</one-to-many>
</attributes>
</entity>
<entity class="Address">
<table name="ADDRESS"/>
<attributes>
<id name="id">
<column name="ADDRESS_ID"/>
</id>
...
<basic name="alias">
<column name="KEY" length="20"/>
</basic>
<many-to-one name="account">
<join-column name="ACCOUNT_ID_OID"/>
</many-to-one>
</attributes>
</entity>
</entity-mappings>
This will create 2 tables in the datastore. One for
Account
, and one for
Address
.
The table for
Address
will contain the key field as well as an index to the
Account
record (notated by the
mapped-by
tag).
|
|