Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/MOXy/JPA/EmbeddedIdClass"

< EclipseLink‎ | Examples‎ | MOXy‎ | JPA
(JAXB Bindings)
(Target Object)
Line 58: Line 58:
  
 
=== Target Object ===
 
=== Target Object ===
 +
 +
As we require support beyond the JAXB spec, we will make use the EclipseLink extension @XmlCustomizer.  Also since the relationship is bidirectional, we will use the EclipseLink extension @XmlInverseReference.
  
 
<source lang="java">
 
<source lang="java">
Line 74: Line 76:
 
}
 
}
 
</source>
 
</source>
 +
 +
If we want the content of the EmployeeId class to be embedded in the complex type corresponding to the Employee class then we can change the XPath on the mapping for the "id" property to be self or ".".
 +
 +
Then we must specify the XPath to the XML nodes which represent the ID.
  
 
<source lang="java">
 
<source lang="java">
Line 83: Line 89:
  
 
     public void customize(ClassDescriptor descriptor) throws Exception {
 
     public void customize(ClassDescriptor descriptor) throws Exception {
         XMLCompositeObjectMapping idMapping = (XMLCompositeObjectMapping) descriptor.getMappingForAttributeName("id");
+
         XMLCompositeObjectMapping idMapping =  
 +
            (XMLCompositeObjectMapping) descriptor.getMappingForAttributeName("id");
 
         idMapping.setXPath(".");
 
         idMapping.setXPath(".");
  

Revision as of 16:01, 1 December 2009

Overview

This example demonstrates how to derive an XML representation from a set of JPA entities using JAXB when a JPA entity has an embedded ID class.

JPA Entities

@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 {
 
    @EmbeddedId
    private EmployeeId id;
 
    @OneToMany(mappedBy="contact")
    private List<PhoneNumber> contactNumber;
 
}
@Embeddable
public class EmployeeId {
 
    @Column(name="E_ID")
    private BigDecimal eId;
 
    private String country;
 
}

JAXB Bindings

For this example the XML acessor type will be set to FIELD for all the model classes. This can be set as a package level JAXB annotation.

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

Target Object

As we require support beyond the JAXB spec, we will make use the EclipseLink extension @XmlCustomizer. Also since the relationship is bidirectional, we will use the EclipseLink extension @XmlInverseReference.

@Entity
@IdClass(EmployeeId.class)
@XmlCustomizer(EmployeeCustomizer.class)
public class Employee {
 
    @EmbeddedId
    private EmployeeId id;
 
    @OneToMany(mappedBy="contact")
    @XmlInverseReference(mappedBy="contact")
    private List<PhoneNumber> contactNumber;
 
}

If we want the content of the EmployeeId class to be embedded in the complex type corresponding to the Employee class then we can change the XPath on the mapping for the "id" property to be self or ".".

Then we must specify the XPath to the XML nodes which represent the ID.

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
 
public class EmployeeCustomizer implements DescriptorCustomizer {
 
    public void customize(ClassDescriptor descriptor) throws Exception {
        XMLCompositeObjectMapping idMapping = 
            (XMLCompositeObjectMapping) descriptor.getMappingForAttributeName("id");
        idMapping.setXPath(".");
 
        descriptor.addPrimaryKeyFieldName("eId/text()");
        descriptor.addPrimaryKeyFieldName("country/text()");
    }
 
}

Source Object

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