Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
EclipseLink/Examples/JPA/2.0/MapKeyColumns
Contents
- 1 How to use Map key columns to map complex Maps
- 1.1 Example of a map key column relationship database
- 1.2 Example of a map key column relationship annotation
- 1.3 Example of a map key column relationship XML
- 1.4 Example of a map key join column relationship database
- 1.5 Example of a map key join column relationship annotation
- 1.6 Example of a map key join column relationship XML
- 1.7 Example of a map key class embedded relationship database
- 1.8 Example of a map key class embedded relationship annotation
- 1.9 Example of a map key class embedded relationship XML
How to use Map key columns to map complex Maps
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.
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 |
Example of a map key column relationship annotation
@Entity public class Employee { @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; ... }
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>
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 |
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; ... }
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> </entity>
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 |
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; ... }
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"> <map-key-class>PhoneType</map-key-class> </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>