Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/JPA2.0/Extended Map support"

(Annotation example)
 
(36 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
= JPA 2.0 Map Support =
 
= JPA 2.0 Map Support =
 +
[[EclipseLink/Development/JPA_2.0 | JPA 2.0 Root]] |
 
[http://bugs.eclipse.org/241410 Enhancement Request]
 
[http://bugs.eclipse.org/241410 Enhancement Request]
 
== Issue summary ==
 
== Issue summary ==
 
: Map support as defined in JPA 2.0 will require new mapping functionality for EclipseLink.  The specification will allow any JPA 1.0 relationship mapping to be stored in a map with key being a primitive, an Embeddable or an Entity.  For this support no user defined mapping or property exists on the target of the relationship as is the case in our current support.  An additional complication is that the location of the Key fields exist on the relation table if one exists.
 
: Map support as defined in JPA 2.0 will require new mapping functionality for EclipseLink.  The specification will allow any JPA 1.0 relationship mapping to be stored in a map with key being a primitive, an Embeddable or an Entity.  For this support no user defined mapping or property exists on the target of the relationship as is the case in our current support.  An additional complication is that the location of the Key fields exist on the relation table if one exists.
 +
 
== The Solution in General ==
 
== The Solution in General ==
: The general approach to implementing this functionality will be to produce Map mappings that encapsulate two EclipseLink mappings.  A generated mapping that represents the Key attribute and a user defined mapping that represents the value of the map.  It is expected that two Map Mappings will be needed.  A Mapping where the Key mapping columns are found in the target table and another where the Key mapping columns are found in the relation table.
+
: Map behavior in EclipseLink is handled through ContainerPolicy.  These mappings will be no different.  a new subclass of MapContainerPolicy (MappedKeyMapContainerPolicy) will be added that is capable of reading and writing map keys that are stored in a database table, but not in the owning Entity, itself.
 +
 
 +
== Use Cases ==
 +
 
 +
Both keys and values can be either of the following types: Basic, Embeddable, Entity.  This results in the following types of maps.
 +
 
 +
=== x - Basic ===
 +
* The mappings: BasicCollectionMapping is used
 +
 
 +
==== Basic - Basic/Embeddable ====
 +
* Both key and value are a basic
 +
* Target table is same for key and for the value
 +
* CollectionTable contains foreign keys to the source, key and the value
 +
* This is BasicMapMapping
 +
* Can also be supported with a BasicCollectionMapping with a MappedKeyMapContainerPolicy containing a DirectToFieldMapping
 +
 
 +
===== Annotation example - Basic key =====
 +
<code><pre>
 +
@ElementCollection
 +
@MapKeyColumn(name="Q_DATE")
 +
@MapKeyTemporal(DATE)
 +
@Column(name="QUOTE")
 +
@CollectionTable(
 +
    name="EXPERT_QUOTES",
 +
    joinColumns=@JoinColumn(name="EBC_ID"))
 +
public Map<Date, String> getQuotes() {
 +
    return quotes;
 +
}
 +
</pre></code>
 +
 
 +
===== XML example - Basic key =====
 +
 
 +
<code><pre>
 +
<element-collection name="quotes">
 +
    <map-key-temporal>DATE</map-key-temporal>
 +
    <map-key-column name="Q_DATE"/>
 +
    <column name="QUOTE"/>
 +
    <collection-table name="EBC_QUOTES">
 +
        <join-column name="EBC_ID"/>
 +
    </collection-table>
 +
</element-collection>
 +
</pre></code>
 +
 
 +
==== Embeddable - Basic ====
 +
* Key is Embeddable, value is Basic
 +
* Information about the key and the value are both stored in the target table
 +
* CollectionTable contains foreign keys to the source, all the fields of the embeddable and the value
 +
* BasicCollectionMapping with MappedKeyMapContainerPolicy containing an AggregateObjectMapping
 +
 
 +
===== Annotation example =====
 +
<code><pre>
 +
@ElementCollection(fetch=EAGER)
 +
@MapKeyClass(Birthday.class)
 +
@AttributeOverrides({
 +
    @AttributeOverride(name="key.day", column=@Column(name="BIRTH_DAY")),
 +
    @AttributeOverride(name="key.month", column=@Column(name="BIRTH_MONTH")),
 +
    @AttributeOverride(name="key.year", column=@Column(name="BIRTH_YEAR"))
 +
})
 +
@Column(name="DETAILS")
 +
@CollectionTable(
 +
    name="EXPERT_CELEBRATIONS",
 +
    joinColumns=@JoinColumn(name="EBC_ID"))
 +
public Map<Birthday, String> getCelebrations() {
 +
    return celebrations;
 +
}
 +
</pre></code>
 +
 
 +
===== XML example =====
 +
<code><pre>
 +
<element-collection name="celebrations" fetch="EAGER">
 +
    <map-key-class class="Birthday"/>
 +
    <map-key-attribute-override name="day">
 +
        <column name="BIRTH_DAY"/>
 +
    </map-key-attribute-override>
 +
    <map-key-attribute-override name="month">
 +
        <column name="BIRTH_MONTH"/>
 +
    </map-key-attribute-override>
 +
    <map-key-attribute-override name="year">
 +
        <column name="BIRTH_YEAR"/>
 +
    </map-key-attribute-override>
 +
    <column name="DETAILS"/>
 +
    <collection-table name="EXPERT_CELEBRATIONS">
 +
        <join-column name="EBC_ID"/>           
 +
    </collection-table>   
 +
</element-collection> 
 +
</pre></code>
 +
 
 +
==== Entity - Basic ====
 +
* Key is Entity, value is Basic
 +
* target table contains foreign keys to the source, foreign keys to the key and the value
 +
* BasicCollectionMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
 +
 
 +
=== x - Embeddable ===
 +
* AggregateCollectionMapping is used
 +
 
 +
==== Basic - Embeddable ====
 +
* Key is a basic, value is Embeddable
 +
* target table contains - foreign keys to the source, key and all attributes of Embeddable
 +
* AggregateCollectionMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping
 +
 
 +
===== Annotation example =====
 +
 
 +
Here the type T is a generic type defined by a sub entity.
 +
 
 +
<code><pre>
 +
@Entity
 +
@Table(name="CMP3_CONSUMER")
 +
@Inheritance(strategy=JOINED)
 +
@DiscriminatorValue(value="BC")
 +
public class BeerConsumer<T>
 +
 
 +
....
 +
 
 +
    @ElementCollection
 +
    // Map key class will get figured out through generic types.
 +
    @MapKeyColumn(name="RS_KEY")
 +
    @CollectionTable(name="CONSUMER_REDSTRIPES", joinColumns=@JoinColumn(name="C_ID", referencedColumnName="ID"))
 +
    public Map<T, RedStripe> getRedStripes() {
 +
        return redStripeBeersToConsume;
 +
    }
 +
 
 +
....
 +
</pre></code>
 +
 
 +
===== XML example - TBD =====
 +
 
 +
==== Embeddable - Embeddable ====
 +
* Key is Embeddable, value is Embeddable
 +
* Uses a Collection Table
 +
* Collection Table contains a forein key, all the fields of both embeddables (note: if key and value map to the same columns through overrides then the table will only contain one set of information about the embeddable)
 +
* AggregateCollectionMapping with MappedKeyMapContainerPolicy containing an AggregateObjectMapping
 +
 
 +
==== Entity - Embeddable ====
 +
* Key is Entity, value is Embeddable
 +
* target table contains foreign keys to the source, foreign keys to the key and all the values of the embedded value
 +
*  AggregateCollectionMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
 +
 
 +
=== x - Entity ===
 +
* The majority of the cases occur when the target is an Entity
 +
* The mappings: OneToMany, UnidirectionalOneToMany and ManyToMany are potentially used
 +
 
 +
==== Basic/Embeddable - Entity ====
 +
* Key is a basic or embeddable, and value is an entity
 +
* Several possible use cases
 +
** Key is a mapped value in target object
 +
*** Covered by our current MapKey support
 +
*** OneToMany, UnidirectionalOneToMany and ManyToMany
 +
** Key is stored in target table, but not mapped in target object
 +
*** target table contains values needed to build the target and values needed to build the key
 +
*** OneToManyMapping or UnidirectionalOneToManyMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping or AggregateObjectMapping
 +
** Key is stored in collection table
 +
*** collection table contains foreign keys to the source, foreign keys to the value, and all fields need to build the key
 +
*** ManyToManyMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping or AggregateObjectMapping
 +
 
 +
===== Annotation example - Embeddable key =====
 +
<code><pre>
 +
@OneToMany(mappedBy="beerConsumer", cascade=ALL)
 +
// MapKeyClass picked up from the generic type
 +
@AttributeOverride(name="number", column=@Column(name="TAG_NUMBER"))
 +
public Map<CoronaTag, Corona> getCoronaBeersToConsume() {
 +
    return coronaBeersToConsume;
 +
}
 +
</pre></code>
 +
 
 +
===== Annotation example - Basic key =====
 +
<code><pre>
 +
@OneToMany(mappedBy="beerConsumer", cascade=ALL, fetch=EAGER)
 +
@MapKeyColumn(name="BOTTLED_DATE")
 +
@MapKeyTemporal(DATE)
 +
public Map<Date, Heineken> getHeinekenBeersToConsume() {
 +
    return heinekenBeersToConsume;
 +
}
 +
</pre></code>
 +
 
 +
===== XML example - Embeddable key =====
 +
<code><pre>
 +
<one-to-many name="coronaBeersToConsume" mapped-by="beerConsumer" target-entity="Corona">
 +
    <!-- map key class picked up from the generic type -->
 +
    <map-key-attribute-override name="number">
 +
        <column name="TAG_NUMBER"/>
 +
    </map-key-attribute-override>
 +
    <cascade>
 +
          <cascade-all/>
 +
    </cascade>
 +
</one-to-many>
 +
</pre></code>
 +
 
 +
===== XML example - Basic key =====
 +
<code><pre>
 +
<one-to-many name="heinekenBeersToConsume" mapped-by="beerConsumer" target-entity="Heineken">
 +
    <map-key-temporal>DATE</map-key-temporal>
 +
    <map-key-column name="BOTTLED_DATE"/>
 +
    <cascade>
 +
        <cascade-all/>
 +
    </cascade>
 +
</one-to-many>
 +
</pre></code>
 +
 
 +
==== Entity - Entity ====
 +
* Key is an Entity, Value is an Entity
 +
* Several possible use cases
 +
** Key is a mapped value in target object
 +
*** Covered by our current MapKey support
 +
*** OneToMany, UnidirectionalOneToMany and ManyToMany
 +
** Key is referenced from target table but not mapped in target object
 +
*** target table contains values need to build the target, and foreign keys to the key
 +
*** OneToManyMapping or UnidirectionalOneToManyMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
 +
** Key is referenced from the collection table
 +
*** collection table contains foreign keys to the source, foreign keys to the value, and foreign keys to the key
 +
*** ManyToManyMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
 +
 
 +
===== Annotation example =====
 +
<code> <pre>
 +
@OneToMany(targetEntity=Becks.class, mappedBy="beerConsumer", cascade=ALL)
 +
@MapKeyClass(BecksTag.class)
 +
@MapKeyJoinColumn(name="TAG_ID", referencedColumnName="ID")
 +
public Map getBecksBeersToConsume() {
 +
    return becksBeersToConsume;
 +
}
 +
</pre></code>
 +
 
 +
===== XML example =====
 +
<code> <pre>
 +
<one-to-many name="becksBeersToConsume" mapped-by="beerConsumer" target-entity="Becks">
 +
    <map-key-class class="BecksTag"/>
 +
    <map-key-join-column name="TAG_ID" referenced-column-name="ID"/>
 +
    <cascade>
 +
        <cascade-all/>
 +
    </cascade>
 +
</one-to-many>
 +
</pre></code>
 +
 
 +
== Design ==
 +
 
 +
* [[EclipseLink/Development/JPA2.0/Extended_Map_support/MappedKeyMapContainerPolicy| MappedKeyMapContainerPolicy]]
 +
 
 +
== Archived Initial Design ==
 +
 
 +
The following contains information about the initial design proposal.  It has now been modified.
 +
 
 +
=== The Solution in General ===
 +
: The general approach to implementing this functionality will be to produce Map mappings that encapsulate two EclipseLink mappings.  A generated mapping that represents the Key attribute and a user defined mapping that represents the value of the map.  It is expected that two Map Mappings will be needed.  A Mapping where the Key mapping columns are found in the target table and another where the Key mapping columns are found in the relation table (CollectionTableMapMapping).
  
== The Details ==
+
=== The Details ===
 
: '''Target Table Map Mapping'''
 
: '''Target Table Map Mapping'''
 
:: [http://bugs.eclipse.org/241412 Enhancement Request]
 
:: [http://bugs.eclipse.org/241412 Enhancement Request]
Line 22: Line 265:
 
::: - ElementCollection<*, Embeddable> mapping
 
::: - ElementCollection<*, Embeddable> mapping
  
: '''Join Table Map Mapping'''
+
: '''Join Table Map Mapping''' (or CollectionTableMapMapping)
 
:: [http://bugs.eclipse.org/241413 Enhancement Request]
 
:: [http://bugs.eclipse.org/241413 Enhancement Request]
 
:: This support will cover the case where the Map key columns exist in the Join table
 
:: This support will cover the case where the Map key columns exist in the Join table
Line 33: Line 276:
 
::: - ManyToMany mapping
 
::: - ManyToMany mapping
 
:::: - Note:  The specification disallows both sides of a mapping using a Map collection but there is no technical reason to do this as one side will be read-only anyway.
 
:::: - Note:  The specification disallows both sides of a mapping using a Map collection but there is no technical reason to do this as one side will be read-only anyway.
 
== Use Cases - Under Construction ==
 
 
Both keys and values can be either of the following types: Basic, Embeddable, Entity.  This results in the following types of maps.
 
 
=== Basic - Basic ===
 
* Both key and value are a basic
 
* Uses a CollectionTable
 
* CollectionTable contains three values - foreign key, key and value
 
 
=== Basic - Embeddable ===
 
* Key is a basic, value is Embeddable
 
* Uses a CollectionTable
 
* Two possible use cases
 
** CollectionTable contains - foreign key, key and all attributes of Embeddable
 
** CollecitonTable contains - foreign key, and all attributes of Embeddable, Key is made up of attributes of Embeddable
 
 
=== Basic - Entity ===
 
* Key is a basic, value is Entity
 
* Several possible use cases
 
** No Join Table (bidirectional OneToMany)
 
*** Key is a Mapped value in Target Entity
 
*** Value is the Target Entity
 
*** Target Entity maps join information
 
** Join Table with Key
 
*** Join table contains foreign keys for each side of the relationship and the key
 
*** Value is the target entity
 
** Join Table with Key on Target
 
*** Join table contains foreign keys for each side of the relationship
 
*** Value is the target entity
 
*** Key is a mapped value of on the target entity
 
 
=== Embeddable - Basic ===
 
* Key is Embeddable, value is Basic
 
* Uses a Collection Table
 
* CollectionTable contains a foreign key, all the fields of the embeddable and the value
 
 
=== Embeddable - Embeddable ===
 
* Key is Embeddable, value is Embeddable
 
* Uses a Collection Table
 
* Collection Table contains a forein key, all the fields of both embeddables (note key and value could be the same embeddable and then the table will only contain one set of information about the embeddable)
 
 
=== Embeddable - Entity ===
 
* Key is Embdeddable, value is Entity
 
* Several Possible use cases
 
** No Join Table
 
*** Key is a Embedded within the Entity
 
*** Value is the Entity itself
 
*** Target Entity Maps Join information
 
** Join Table with Key
 
*** Join table contains foreign keys for each Entity and fields of Embeddable
 
*** Value is the target entity
 
** Join Table no key
 
*** Join table contains foreign keys for each Entity
 
*** Key is Embedded in target Entity
 
*** Value is target Entity
 
 
=== Entity - Basic ===
 
* Key is Entity, value is Basic
 
* Uses a Collection Table
 
* Collection table contains foreign key to the source, foreign keys to the key and the value
 
 
=== Entity - Embeddable ===
 
* Key is Entity, value is Embeddable
 
* Uses a Colleciton Table
 
* Collection table contains foreign key to the source, foreign keys to the key and all the values of the embedded value
 
 
=== Entity - Entity ===
 
* Key is Entity, value is Entity
 
* Uses a Join table
 
* Join table contains foreign keys to the source, foreign keys to the key and foreign keys to the value
 

Latest revision as of 16:01, 3 April 2009

JPA 2.0 Map Support

JPA 2.0 Root | Enhancement Request

Issue summary

Map support as defined in JPA 2.0 will require new mapping functionality for EclipseLink. The specification will allow any JPA 1.0 relationship mapping to be stored in a map with key being a primitive, an Embeddable or an Entity. For this support no user defined mapping or property exists on the target of the relationship as is the case in our current support. An additional complication is that the location of the Key fields exist on the relation table if one exists.

The Solution in General

Map behavior in EclipseLink is handled through ContainerPolicy. These mappings will be no different. a new subclass of MapContainerPolicy (MappedKeyMapContainerPolicy) will be added that is capable of reading and writing map keys that are stored in a database table, but not in the owning Entity, itself.

Use Cases

Both keys and values can be either of the following types: Basic, Embeddable, Entity. This results in the following types of maps.

x - Basic

  • The mappings: BasicCollectionMapping is used

Basic - Basic/Embeddable

  • Both key and value are a basic
  • Target table is same for key and for the value
  • CollectionTable contains foreign keys to the source, key and the value
  • This is BasicMapMapping
  • Can also be supported with a BasicCollectionMapping with a MappedKeyMapContainerPolicy containing a DirectToFieldMapping
Annotation example - Basic key
@ElementCollection
@MapKeyColumn(name="Q_DATE")
@MapKeyTemporal(DATE)
@Column(name="QUOTE")
@CollectionTable(
    name="EXPERT_QUOTES",
    joinColumns=@JoinColumn(name="EBC_ID"))
public Map<Date, String> getQuotes() {
    return quotes;
}
XML example - Basic key
<element-collection name="quotes">
    <map-key-temporal>DATE</map-key-temporal>
    <map-key-column name="Q_DATE"/>
    <column name="QUOTE"/>
    <collection-table name="EBC_QUOTES">
        <join-column name="EBC_ID"/>
    </collection-table>
</element-collection>

Embeddable - Basic

  • Key is Embeddable, value is Basic
  • Information about the key and the value are both stored in the target table
  • CollectionTable contains foreign keys to the source, all the fields of the embeddable and the value
  • BasicCollectionMapping with MappedKeyMapContainerPolicy containing an AggregateObjectMapping
Annotation example
@ElementCollection(fetch=EAGER)
@MapKeyClass(Birthday.class)
@AttributeOverrides({
    @AttributeOverride(name="key.day", column=@Column(name="BIRTH_DAY")),
    @AttributeOverride(name="key.month", column=@Column(name="BIRTH_MONTH")),
    @AttributeOverride(name="key.year", column=@Column(name="BIRTH_YEAR"))
})
@Column(name="DETAILS")
@CollectionTable(
    name="EXPERT_CELEBRATIONS",
    joinColumns=@JoinColumn(name="EBC_ID"))
public Map<Birthday, String> getCelebrations() {
    return celebrations;
}
XML example
<element-collection name="celebrations" fetch="EAGER">
    <map-key-class class="Birthday"/>
    <map-key-attribute-override name="day">
        <column name="BIRTH_DAY"/>
    </map-key-attribute-override>
    <map-key-attribute-override name="month">
        <column name="BIRTH_MONTH"/>
    </map-key-attribute-override>
    <map-key-attribute-override name="year">
        <column name="BIRTH_YEAR"/>
    </map-key-attribute-override>
    <column name="DETAILS"/>
    <collection-table name="EXPERT_CELEBRATIONS">
        <join-column name="EBC_ID"/>            
     </collection-table>    
</element-collection>  

Entity - Basic

  • Key is Entity, value is Basic
  • target table contains foreign keys to the source, foreign keys to the key and the value
  • BasicCollectionMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping

x - Embeddable

  • AggregateCollectionMapping is used

Basic - Embeddable

  • Key is a basic, value is Embeddable
  • target table contains - foreign keys to the source, key and all attributes of Embeddable
  • AggregateCollectionMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping
Annotation example

Here the type T is a generic type defined by a sub entity.

@Entity
@Table(name="CMP3_CONSUMER")
@Inheritance(strategy=JOINED)
@DiscriminatorValue(value="BC")
public class BeerConsumer<T>

....

    @ElementCollection
    // Map key class will get figured out through generic types.
    @MapKeyColumn(name="RS_KEY")
    @CollectionTable(name="CONSUMER_REDSTRIPES", joinColumns=@JoinColumn(name="C_ID", referencedColumnName="ID"))
    public Map<T, RedStripe> getRedStripes() {
        return redStripeBeersToConsume;
    }

....
XML example - TBD

Embeddable - Embeddable

  • Key is Embeddable, value is Embeddable
  • Uses a Collection Table
  • Collection Table contains a forein key, all the fields of both embeddables (note: if key and value map to the same columns through overrides then the table will only contain one set of information about the embeddable)
  • AggregateCollectionMapping with MappedKeyMapContainerPolicy containing an AggregateObjectMapping

Entity - Embeddable

  • Key is Entity, value is Embeddable
  • target table contains foreign keys to the source, foreign keys to the key and all the values of the embedded value
  • AggregateCollectionMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping

x - Entity

  • The majority of the cases occur when the target is an Entity
  • The mappings: OneToMany, UnidirectionalOneToMany and ManyToMany are potentially used

Basic/Embeddable - Entity

  • Key is a basic or embeddable, and value is an entity
  • Several possible use cases
    • Key is a mapped value in target object
      • Covered by our current MapKey support
      • OneToMany, UnidirectionalOneToMany and ManyToMany
    • Key is stored in target table, but not mapped in target object
      • target table contains values needed to build the target and values needed to build the key
      • OneToManyMapping or UnidirectionalOneToManyMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping or AggregateObjectMapping
    • Key is stored in collection table
      • collection table contains foreign keys to the source, foreign keys to the value, and all fields need to build the key
      • ManyToManyMapping with MappedKeyMapContainerPolicy containing a DirectToFieldMapping or AggregateObjectMapping
Annotation example - Embeddable key
@OneToMany(mappedBy="beerConsumer", cascade=ALL)
// MapKeyClass picked up from the generic type
@AttributeOverride(name="number", column=@Column(name="TAG_NUMBER"))
public Map<CoronaTag, Corona> getCoronaBeersToConsume() {
    return coronaBeersToConsume;
}
Annotation example - Basic key
@OneToMany(mappedBy="beerConsumer", cascade=ALL, fetch=EAGER)
@MapKeyColumn(name="BOTTLED_DATE")
@MapKeyTemporal(DATE)
public Map<Date, Heineken> getHeinekenBeersToConsume() {
    return heinekenBeersToConsume;
}
XML example - Embeddable key
<one-to-many name="coronaBeersToConsume" mapped-by="beerConsumer" target-entity="Corona">
    <!-- map key class picked up from the generic type -->
    <map-key-attribute-override name="number">
        <column name="TAG_NUMBER"/>
    </map-key-attribute-override>
    <cascade>
          <cascade-all/>
    </cascade>
</one-to-many>
XML example - Basic key
<one-to-many name="heinekenBeersToConsume" mapped-by="beerConsumer" target-entity="Heineken">
    <map-key-temporal>DATE</map-key-temporal>
    <map-key-column name="BOTTLED_DATE"/>
    <cascade>
        <cascade-all/>
    </cascade>
</one-to-many>

Entity - Entity

  • Key is an Entity, Value is an Entity
  • Several possible use cases
    • Key is a mapped value in target object
      • Covered by our current MapKey support
      • OneToMany, UnidirectionalOneToMany and ManyToMany
    • Key is referenced from target table but not mapped in target object
      • target table contains values need to build the target, and foreign keys to the key
      • OneToManyMapping or UnidirectionalOneToManyMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
    • Key is referenced from the collection table
      • collection table contains foreign keys to the source, foreign keys to the value, and foreign keys to the key
      • ManyToManyMapping with MappedKeyMapContainerPolicy containing a OneToOneMapping
Annotation example
@OneToMany(targetEntity=Becks.class, mappedBy="beerConsumer", cascade=ALL)
@MapKeyClass(BecksTag.class)
@MapKeyJoinColumn(name="TAG_ID", referencedColumnName="ID")
public Map getBecksBeersToConsume() {
    return becksBeersToConsume;
}
XML example
<one-to-many name="becksBeersToConsume" mapped-by="beerConsumer" target-entity="Becks">
    <map-key-class class="BecksTag"/>
    <map-key-join-column name="TAG_ID" referenced-column-name="ID"/>
    <cascade>
        <cascade-all/>
    </cascade>
</one-to-many>

Design

Archived Initial Design

The following contains information about the initial design proposal. It has now been modified.

The Solution in General

The general approach to implementing this functionality will be to produce Map mappings that encapsulate two EclipseLink mappings. A generated mapping that represents the Key attribute and a user defined mapping that represents the value of the map. It is expected that two Map Mappings will be needed. A Mapping where the Key mapping columns are found in the target table and another where the Key mapping columns are found in the relation table (CollectionTableMapMapping).

The Details

Target Table Map Mapping
Enhancement Request
This support will cover the case where the Map key columns exist in the target table
EclipseLink Mappings Involved
- AggregateCollectionMapping
- Bi-directional OneToMany
- New Uni-directional OneToMany mapping
JPA Mappings
- Bi-directional OneToMany mapping
- Uni-directional OneToMany with @JoinColum
- ElementCollection<*, Primitive> mapping
- ElementCollection<*, Embeddable> mapping
Join Table Map Mapping (or CollectionTableMapMapping)
Enhancement Request
This support will cover the case where the Map key columns exist in the Join table
EclipseLink Mappings Involved
- ManyToMany mapping
JPA Mappings
- default Uni-directional OneToMany with @JoinColum
- ManyToMany mapping
- Note: The specification disallows both sides of a mapping using a Map collection but there is no technical reason to do this as one side will be read-only anyway.

Back to the top