Jump to: navigation, search

Difference between revisions of "EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys/Composite Key"

Line 2: Line 2:
 
|info=y
 
|info=y
 
|api=y
 
|api=y
 +
|toc=y
 
|apis= * [http://www.eclipse.org/eclipselink/api/latest/javax/xml/bind/annotation/XmlAccessType.html javax.xml.bind.annotation.XmlAccessType]
 
|apis= * [http://www.eclipse.org/eclipselink/api/latest/javax/xml/bind/annotation/XmlAccessType.html javax.xml.bind.annotation.XmlAccessType]
 
* [http://www.eclipse.org/eclipselink/api/latest/javax/xml/bind/annotation/XmlCustomizer.html javax.xml.bind.annotation.XmlCustomizer]
 
* [http://www.eclipse.org/eclipselink/api/latest/javax/xml/bind/annotation/XmlCustomizer.html javax.xml.bind.annotation.XmlCustomizer]
Line 9: Line 10:
 
}}  
 
}}  
  
=Mapping Single Key Relationships=
+
=Mapping Composite Key Relationships=
  
To model non-privately-owned relationships, your "target" objects must have IDs (keys) defined, and your "source" object must use these IDs to map the relationship.
+
If the objects that you want to map have multi-part keys (i.e., a combination of fields that determines uniqueness), you can use EclipseLink's '''@XmlKey''' and '''@XmlJoinNodes''' to set up this relationship.
  
Relationships represented with keys use the '''@XmlID''' and '''@XmlIDREF''' annotations.  Although the JAXB specification requires that the property marked with '''@XmlID''' be a '''String''', MOXy JAXB does not enforce this restriction.
+
In this example, each '''Employee''' has one '''manager''' but multiple '''reports''', and '''Employees''' are uniquely identified by the combination of their '''id''' and '''name''' fields.
 
+
In this example, each '''Employee''' has one '''manager''' but multiple '''reports'''.
+
  
 
<source lang="java">
 
<source lang="java">
 
@XmlAccessorType(XmlAccessType.FIELD)
 
@XmlAccessorType(XmlAccessType.FIELD)
 
public class Employee {
 
public class Employee {
 +
    @XmlID
 
     @XmlAttribute
 
     @XmlAttribute
    @XmlID
 
 
     private Integer id;
 
     private Integer id;
 
   
 
   
 +
    @XmlKey
 
     @XmlAttribute
 
     @XmlAttribute
 
     private String name;
 
     private String name;
 
   
 
   
     @XmlIDREF
+
     @XmlJoinNodes( {
     private Employee manager;
+
        @XmlJoinNode(xmlPath = "manager/@id", referencedXmlPath = "@id"),
+
        @XmlJoinNode(xmlPath = "manager/@name", referencedXmlPath = "@name") })
     @XmlElement(name="report")
+
     public Employee manager;
    @XmlIDREF
+
 
     private List<Employee> reports;
+
     @XmlJoinNodes( {
 +
        @XmlJoinNode(xmlPath = "report/@id", referencedXmlPath = "@id"),
 +
        @XmlJoinNode(xmlPath = "report/@name", referencedXmlPath = "@name") })
 +
     public List<Employee> reports = new ArrayList<Employee>();
  
 
     ...
 
     ...

Revision as of 14:44, 16 March 2011

EclipseLink MOXy

Mapping Composite Key Relationships

If the objects that you want to map have multi-part keys (i.e., a combination of fields that determines uniqueness), you can use EclipseLink's @XmlKey and @XmlJoinNodes to set up this relationship.

In this example, each Employee has one manager but multiple reports, and Employees are uniquely identified by the combination of their id and name fields.

@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
    @XmlID
    @XmlAttribute
    private Integer id;
 
    @XmlKey
    @XmlAttribute
    private String name;
 
    @XmlJoinNodes( {
        @XmlJoinNode(xmlPath = "manager/@id", referencedXmlPath = "@id"),
        @XmlJoinNode(xmlPath = "manager/@name", referencedXmlPath = "@name") })
    public Employee manager;
 
    @XmlJoinNodes( {
        @XmlJoinNode(xmlPath = "report/@id", referencedXmlPath = "@id"),
        @XmlJoinNode(xmlPath = "report/@name", referencedXmlPath = "@name") })
    public List<Employee> reports = new ArrayList<Employee>();
 
    ...
}

The following example shows how to define this mapping information in EclipseLink's OXM metadata format.

...
<java-type name="Employee">
   <java-attributes>
      <xml-attribute java-attribute="id" type="java.lang.Integer" xml-id="true"/>
      <xml-attribute java-attribute="name" type="java.lang.String"/>
      <xml-element java-attribute="manager" type="mypackage.Employee" xml-idref="true"/>
      <xml-element java-attribute="reports" type="mypackage.Employee" container-type="java.util.ArrayList" xml-idref="true"/>
   </java-attributes>
</java-type>
...

This would produce the following XML:

<company>
    <employee id="1" name="Jane Doe">
        <report>2</report>
        <report>3</report>
    </employee>
    <employee id="2" name="John Smith">
        <manager>1</manager>
    </employee>
    <employee id="3" name="Anne Jones">
        <manager>1</manager>
    </employee>
</company>

The manager and reports elements contain the IDs of the Employee instances they are referencing.


Using @XmlList

Because the @XmlIDREF annotation is also compatible with the @XmlList annotation, the Employee object could be modeled as:

@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
    @XmlID
    @XmlAttribute
    private Integer id;
 
    @XmlAttribute
    private String name;
 
    @XmlIDREF
    private Employee manager;
 
    @XmlIDREF
    @XmlList
    private List<Employee> reports;
 
    ... 
}

This would produce the following XML:

<company>
   <employee id="1" name="Jane Doe">
      <reports>2 3</reports>
   </employee>
   <employee id="2" name="John Smith">
      <manager>1</manager>
   </employee>
   <employee id="3" name="Anne Jones">
      <manager>1</manager>
   </employee>
</company>

Eclipselink-logo.gif
Version: 2.2.0 DRAFT
Other versions...