Jump to: navigation, search

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

m
m
Line 2: Line 2:
 
|info=y
 
|info=y
 
|api=y
 
|api=y
|apis=  
+
|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
 
|eclipselink=y
 
|eclipselinktype=MOXy
 
|eclipselinktype=MOXy
Line 50: Line 52:
 
</source>
 
</source>
  
In this example, set the '''XmlAccessType''' to '''FIELD''' for each model class. You can consigure this as a package-level JAXB annotation, as shown here:
+
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">
 
<source lang="java">

Revision as of 14:39, 6 January 2011

EclipseLink 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:

@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;
 
}

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:

@XmlAccessorType(XmlAccessType.FIELD)
package com.example.model;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

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:

@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;
 
}

You must also specify the XPath to the XML nodes which represent the ID:

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 Object

If the target object had a single ID then we would use @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.

@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;
 
}

EclipseLink creates the XMLObjectReferenceMapping. This mapping includes multiple key mappings.

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);
    }
 
}


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