Jump to: navigation, search

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

m
m (Replacing page with 'See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/shared_reference_relationships004.htm')
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{EclipseLink_UserGuide
+
See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/shared_reference_relationships004.htm
|info=y
+
|api=y
+
|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/XmlInverseReference.html javax.xml.bind.annotation.XmlInverseReference]
+
|eclipselink=y
+
|eclipselinktype=MOXy
+
}}
+
 
+
= Using Composite (Compound) Primary Keys =
+
With JAXB, you can generate XML from a set of JPA entities with composite (compound) primary keys.
+
 
+
For example, consider the following example:
+
 
+
<source lang="java">
+
@Entity
+
public class PhoneNumber {
+
 
+
    @ManyToOne
+
    @JoinColumns({
+
        @JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
+
        @JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
+
    })
+
 
+
    private Employee contact;
+
 
+
}
+
 
+
@Entity
+
@IdClass(EmployeeId.class)
+
public class Employee {
+
 
+
    @Id
+
    @Column(name="E_ID")
+
    private BigDecimal eId;
+
 
+
    @Id
+
    private String country;
+
 
+
    @OneToMany(mappedBy="contact")
+
    private List<PhoneNumber> contactNumber;
+
 
+
}
+
 
+
public class EmployeeId {
+
 
+
    private BigDecimal eId;
+
    private String country;
+
 
+
}
+
</source>
+
 
+
In this example, set the '''XmlAccessType''' to '''FIELD''' for each model class. You can configure this as a package-level JAXB annotation, as shown here:
+
 
+
<source lang="java">
+
@XmlAccessorType(XmlAccessType.FIELD)
+
package com.example.model;
+
 
+
import javax.xml.bind.annotation.XmlAccessType;
+
import javax.xml.bind.annotation.XmlAccessorType;
+
</source>
+
 
+
=== Target Object ===
+
You can use the EclispeLink '''@XmlCustomizer''' for configuration options beyond the JAXB specification. Because the relationship is bidirectional, you must use the '''@XmlInverseReference''' extension, as shown here:
+
 
+
<source lang="java">
+
@Entity
+
@IdClass(EmployeeId.class)
+
@XmlCustomizer(EmployeeCustomizer.class)
+
public class Employee {
+
 
+
    @Id
+
    @Column(name="E_ID")
+
    private BigDecimal eId;
+
 
+
    @Id
+
    private String country;
+
 
+
    @OneToMany(mappedBy="contact")
+
    @XmlInverseReference(mappedBy="contact")
+
    private List<PhoneNumber> contactNumber;
+
 
+
}
+
</source>
+
 
+
You must also specify the XPath to the XML nodes which represent the ID:
+
 
+
<source lang="java">
+
import org.eclipse.persistence.config.DescriptorCustomizer;
+
import org.eclipse.persistence.descriptors.ClassDescriptor;
+
 
+
public class EmployeeCustomizer implements DescriptorCustomizer {
+
 
+
    public void customize(ClassDescriptor descriptor) throws Exception {
+
        descriptor.addPrimaryKeyFieldName("eId/text()");
+
        descriptor.addPrimaryKeyFieldName("country/text()");
+
    }
+
 
+
}
+
</source>
+
 
+
=== Source Object ===
+
 
+
If the target object had a single ID then we would use '''[[EclipseLink/UserGuide/MOXy/Relationships/Shared_Reference/Keys_and_Foreign_Keys/Single_Key|@XmlIDREF]]'''.  Because the target object has a ''compound key'', use the '''@XmlTransient''' annotation.
+
 
+
Use the EclipseLink '''@XmlCustomizer''' extension to create the mapping as shown here.
+
 
+
<source lang="java">
+
@Entity
+
@XmlCustomizer(PhoneNumberCustomizer.class)
+
public class PhoneNumber {
+
 
+
    @ManyToOne
+
    @JoinColumns({
+
        @JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
+
        @JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
+
    })
+
    @XmlTransient
+
    private Employee contact;
+
 
+
}
+
</source>
+
 
+
EclipseLink creates the '''XMLObjectReferenceMapping'''.  This mapping includes multiple key mappings.
+
 
+
<source lang="java">
+
import org.eclipse.persistence.config.DescriptorCustomizer;
+
import org.eclipse.persistence.descriptors.ClassDescriptor;
+
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;
+
 
+
public class PhoneNumberCustomizer implements DescriptorCustomizer {
+
 
+
    public void customize(ClassDescriptor descriptor) throws Exception {
+
        XMLObjectReferenceMapping contactMapping = new XMLObjectReferenceMapping();
+
        contactMapping.setAttributeName("contact");
+
        contactMapping.setReferenceClass(Employee.class);
+
        contactMapping.addSourceToTargetKeyFieldAssociation("contact/@eID", "eId/text()");
+
        contactMapping.addSourceToTargetKeyFieldAssociation("contact/@country", "country/text()");
+
        descriptor.addMapping(contactMapping);
+
    }
+
 
+
}
+
</source>
+
 
+
 
+
 
+
{{EclipseLink_MOXy
+
|previous=[[EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys/Single Key|Single Key]]
+
|up      =[[EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys|Keys and Foreign Keys]]
+
|next    =[[EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys/Embedded Key Class|Embedded Key Class]]
+
|version=2.2.0 DRAFT
+
}}
+

Latest revision as of 09:27, 8 November 2012

See http://www.eclipse.org/eclipselink/documentation/2.4/moxy/shared_reference_relationships004.htm