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/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys/Composite Key"

m
m
Line 3: Line 3:
 
|api=y
 
|api=y
 
|apis=  
 
|apis=  
 +
|eclipselink=y
 +
|eclipselinktype=MOXy
 
}}  
 
}}  
  

Revision as of 14:37, 6 January 2011

EclipseLink MOXy

Eclipselink-logo.gif
EclipseLink
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source

Elug api package icon.png Key API


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 consigure 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...

Back to the top