• Variable OneToOne, ManyToOne - A reference to an interface or common unmapped inheritance class that has multiple distinct implementors.
• Variable OneToMany, ManyToMany - A Collection or Map of heterogeneous objects that share an interface or common unmapped inheritance class that has multiple distinct implementers.
• Nested collection relationships, such as an array of arrays, List of Lists, or Map of Maps, or other such combinations.
• Object-Relational Data Type - Relationships stored in the database using STRUCT, VARRAY, REF, or NESTEDTABLE types.
• XML relationships - Relationships stored as XML documents.
[edit] Maps
Java defines the Map interface to represent collections whose values are indexed on a key. There are several Map implementations, the most common is HashMap, but also Hashtable and
TreeMap.
JPA allows a Map to be used for any collection mapping including, OneToMany, ManyToMany and ElementCollection. JPA requires that the Map interface be used as the attribute type, although some JPA providers may also support using Map implementations.
In JPA 1.0 the map key must be a mapped attribute of the collection values. The @MapKey
annotation or <map-key> XML element is used to define a map relationship. If the MapKey is not specified it defaults to the target object's Id.
[edit] Example of a map key relationship annotation
@Entity
public class Employee { @Id
private long id; ...
@OneToMany(mappedBy="owner") @MapKey(name="type")
private Map<String, PhoneNumber> phoneNumbers; ...
}
@Entity
public class PhoneNumber { @Id
private long id; @Basic
private String type; // Either "home", "work", or "fax". ...
@ManyToOne
private Employee owner; ...
}
[edit] Example of a map key relationship XML
<entity name="Employee" class="org.acme.Employee" access="FIELD"> <attributes>
<id name="id"/>
<one-to-many name="phoneNumbers" mapped-by="owner"> <map-key name="type"/>
</one-to-many> </attributes> </entity>
<entity name="PhoneNumber" class="org.acme.PhoneNumber" access="FIELD"> <attributes>
<id name="id"/> <basic name="type"/>
<many-to-one name="owner"/> </attributes>
</entity>
[edit] Map Key Columns (JPA 2.0)
JPA 2.0 allows for a Map where the key is not part of the target object to be persisted. The Map key can be any of the following:
• A Basic value, stored in the target's table or join table.
• An Embedded object, stored in the target's table or join table.
• A foreign key to another Entity, stored in the target's table or join table.
Map columns can be used for any collection mapping including, OneToMany, ManyToMany and ElementCollection.
This allows for great flexibility and complexity in the number of different models that can be mapped. The type of mapping used is always determined by the value of the Map, not the key. So if the key is a Basic but the value is an Entity a OneToMany mapping is still used. But if the value is a Basic but the key is an Entity a ElementCollection mapping is used.
This allows some very sophisticated database schemas to be mapped. Such as a three way join table, can be mapped using a ManyToMany with a MapKeyJoinColumn for the third foreign key. For a ManyToMany the key is always stored in the JoinTable. For a OneToMany it is stored in the JoinTable if defined, otherwise it is stored in the target Entity's table, even though the target Entity does not map this column. For an ElementCollection the key is stored in the element's table.
The @MapKeyColumn annotation or <map-key-column> XML element is used to define a map
relationship where the key is a Basic value, the @MapKeyEnumerated and @MapKeyTemporal can
also be used with this for Enum or Calendar types. The @MapKeyJoinColumn annotation or
<map-key-join-column> XML element is used to define a map relationship where the key is an Entity value, the @MapKeyJoinColumns can also be used with this for composite foreign keys.
The annotation @MapKeyClass or <map-key-class> XML element can be used when the key is
an Embeddable or to specify the target class or type if generics are not used.
[edit] Example of a map key column relationship database
EMPLOYEE (table)
ID FIRSTNAME LASTNAME SALARY
1 Bob Way 50000
2 Sarah Smith 60000 PHONE(table)
ID OWNER_ID PHONE_TYPE AREACODE NUMBER
1 1 home 613 792-7777
2 1 cell 613 798-6666
3 2 home 416 792-9999
4 2 fax 416 798-5555
[edit] Example of a map key column relationship annotation
@Entity
@Id
private long id; ...
@OneToMany(mappedBy="owner") @MapKeyColumn(name="PHONE_TYPE") private Map<String, Phone> phones; ...
}
@Entity
public class Phone { @Id
private long id; ...
@ManyToOne
private Employee owner; ...
}
[edit] Example of a map key column relationship XML
<entity name="Employee" class="org.acme.Employee" access="FIELD"> <attributes>
<id name="id"/>
<one-to-many name="phones" mapped-by="owner"> <map-key-column name="PHONE_TYPE"/>
</one-to-many> </attributes> </entity>
<entity name="Phone" class="org.acme.Phone" access="FIELD"> <attributes>
<id name="id"/>
<many-to-one name="owner"/> </attributes>
</entity>
[edit] Example of a map key join column relationship database
EMPLOYEE (table)
ID FIRSTNAME LASTNAME SALARY
1 Bob Way 50000
2 Sarah Smith 60000 PHONE(table)
ID OWNER_ID PHONE_TYPE_ID AREACODE NUMBER
1 1 1 613 792-7777 2 1 2 613 798-6666 3 2 1 416 792-9999 4 2 3 416 798-5555 PHONETYPE(table) ID TYPE 1 home 2 cell 3 fax
4 work
[edit] Example of a map key join column relationship annotation
@Entity
public class Employee { @Id
private long id; ...
@OneToMany(mappedBy="owner")
@MapKeyJoinColumn(name="PHONE_TYPE_ID") private Map<PhoneType, Phone> phones; ...
}
@Entity
public class Phone { @Id
private long id; ...
@ManyToOne
private Employee owner; ...
}
@Entity
public class PhoneType { @Id
private long id; ...
@Basic
private String type; ...
}
[edit] Example of a map key join column relationship XML
<entity name="Employee" class="org.acme.Employee" access="FIELD"> <attributes>
<id name="id"/>
<one-to-many name="phones" mapped-by="owner"> <map-key-join-column name="PHONE_TYPE_ID"/> </one-to-many>
</attributes> </entity>
<entity name="Phone" class="org.acme.Phone" access="FIELD"> <attributes>
<id name="id"/>
<many-to-one name="owner"/> </attributes>
</entity>
<entity name="PhoneType" class="org.acme.PhoneType" access="FIELD"> <attributes>
<id name="id"/> <basic name="type"/> </attributes>
[edit] Example of a map key class embedded relationship database
EMPLOYEE (table)
ID FIRSTNAME LASTNAME SALARY
1 Bob Way 50000
2 Sarah Smith 60000 EMPLOYEE_PHONE (table)
EMPLOYEE_ID PHONE_ID TYPE
1 1 home 1 2 cell 2 3 home 2 4 fax PHONE (table) ID AREACODE NUMBER 1 613 792-7777 2 613 798-6666 3 416 792-9999 4 416 798-5555
[edit] Example of a map key class embedded relationship annotation
@Entity
public class Employee { @Id
private long id; ...
@OneToMany
@MapKeyClass(PhoneType.class)
private Map<PhoneType, Phone> phones; ...
}
@Entity
public class Phone { @Id
private long id; ...
}
@Embeddable
public class PhoneType { @Basic
private String type; ...
}
[edit] Example of a map key class embedded relationship XML
<entity name="Employee" class="org.acme.Employee" access="FIELD"> <attributes>
<id name="id"/>
<one-to-many name="phones">
</one-to-many> </attributes> </entity>
<entity name="Phone" class="org.acme.Phone" access="FIELD"> <attributes>
<id name="id"/>
<many-to-one name="owner"/> </attributes>
</entity>
<embeddable name="PhoneType" class="org.acme.PhoneType" access="FIELD"> <attributes>
<basic name="type"/> </attributes>
</embeddable>