Notice: This Wiki is now read only and edits are no longer 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 1: | Line 1: | ||
− | |||
− | |||
− | |||
{{EclipseLink_UserGuide | {{EclipseLink_UserGuide | ||
|info=y | |info=y | ||
− | |||
|api=y | |api=y | ||
|apis= | |apis= | ||
Line 10: | Line 6: | ||
= Using Composite (Compound) Primary Keys = | = 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 consigure 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> | ||
Line 17: | Line 146: | ||
|up =[[EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys|Keys and Foreign Keys]] | |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]] | |next =[[EclipseLink/UserGuide/MOXy/Relationships/Shared Reference/Keys and Foreign Keys/Embedded Key Class|Embedded Key Class]] | ||
− | |version=2.2.0 | + | |version=2.2.0 DRAFT |
}} | }} |
Revision as of 14:36, 6 January 2011
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); } }