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.
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 | |
Website | |
Download | |
Community | |
Mailing List • Forums • IRC • mattermost | |
Issues | |
Open • Help Wanted • Bug Day | |
Contribute | |
Browse Source |
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); } }