この章の内容は次のとおりです。
この項では、オブジェクト間の1対1リレーションシップをマップする方法をいくつか示します。デフォルトでは、1対1リレーションシップはJAXB内で私有であり、そのXMLコンテンツは、所有側の要素の内側にネストされて表示されます。たとえば、PhoneNumberに1対1マッピングされているCustomerは、次のようにマーシャリングされます。
例6-1 XMLマッピングのサンプル
<customer>
<name>Bob Smith</name>
<id>1982812</id>
<phone-number>
<area-code>613</area-code>
<number>5550210</number>
<extension>20016</extension>
</phone-number>
</customer>
例6-2のXMLスキーマであると仮定して、図6-1は、2つの複雑なタイプ間での1対1 (1:1)リレーションシップを示します。
例6-2 XMLスキーマのサンプル
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customer" type="customer-type"/>
<xsd:complexType name="customer-type">
<xsd:element name="phone-number" type="phone-type"/>
</xsd:complexType>
<xsd:complexType name="phone-type">
<xsd:element name="area-code" type="xsd:int"/>
<xsd:element name="number" type="xsd:int"/>
<xsd:element name="extension" type="xsd:int"/>
</xsd:complexType>
</xsd:schema>
例6-3は、EclipseLinkでこのマッピングを取得するためにJavaクラスに注釈を付ける方法を示しています。JAXBの標準的な@XmlElement注釈を使用して、関連付けられているJavaフィールドをXML要素にマップする必要があることを示すことができます。
|
注意: デフォルトでは、JAXBは、Javaオブジェクト上のすべてのフィールドが@XmlElementであるとするため、多くの場合、注釈自体が不要です。ただし、JavaフィールドのXML名をカスタマイズする場合は、name引数を付けて@XmlElement注釈を指定できます。 |
例6-3 @XmlElement注釈の使用
package example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlElement(name="phone-number")
private PhoneNumber phoneNumber;
...
}
package example;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
@XmlElement(name="area-code")
private Integer areaCode;
private Integer number;
private Integer extension;
...
}
例6-4は、EclipseLinkのXMLバインディング・ドキュメントにマッピング情報を定義する方法を示しています。
例6-4 XMLマッピングのサンプル
...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-element java-attribute="phoneNumber" name="phone-number" type="PhoneNumber"/>
</java-attributes>
</java-type>
<java-type name="PhoneNumber">
<java-attributes>
<xml-value java-attribute="areaCode" name="area-code" type="java.lang.Integer"/>
<xml-value java-attribute="number" type="java.lang.Integer"/>
<xml-value java-attribute="extension" type="java.lang.Integer"/>
</java-attributes>
</java-type>
...
デフォルトでは、Java属性は、その属性のJava名に基づいて、または@XmlElement注釈に指定された名前別に、XMLにマップされます。このマッピングはXPathに基づいており、EclipseLinkの@XmlPath注釈を使用すると、このマッピングをカスタマイズできます。たとえば、これを使用すると、XMLでの要素のネストを制御できます。
例6-5 @XmlPath注釈の使用
package example;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlPath("contact-info/phone-number")
private PhoneNumber phoneNumber;
...
}
例6-6 EclipseLinkのXMLバインディングの使用
...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-element java-attribute="phoneNumber" name="phone-number"
type="PhoneNumber" xml-path="contact-info/phone-number"/>
</java-attributes>
</java-type>
...
これにより、次のXMLが生成されます。
<customer>
<contact-info>
<phone-number>
<number>555-631-2124</number>
</phone-number>
</contact-info>
</customer>
@XmlPathを使用して、XML内での同じ要素の別のオカレンスに索引別にマップすることもできます。次に例を示します。
例6-7 @XmlPath注釈の使用
package example;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlPath("contact-info/phone[1]")
private PhoneNumber homePhone;
@XmlPath("contact-info/phone[2]")
private PhoneNumber workPhone;
...
}
生成されるXMLは次のとおりです。
<customer>
<contact-info>
<phone>
<number>555-631-2124</number>
</phone>
<phone>
<number>555-631-8298</number>
</phone>
</contact-info>
</customer>
マッピングでのXPathの使用方法の詳細は、「マッピング用のXPath述語の使用」を参照してください。
この項では、EclipseLinkとの1対多リレーションシップをマップする方法を示します。
例6-8のスキーマは、図6-2に示されているとおり、CustomerとPhoneNumberの間にある典型的な1対多(1:M)リレーションシップです。
例6-8 XMLマッピングのサンプル
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customer" type="customer-type"/>
<xsd:complexType name="customer-type">
<xsd:sequence>
<xsd:element name="first-name" type="xsd:string"/>
<xsd:element name="last-name" type="xsd:string"/>
<xsd:element name="phone-number" type="phone-type" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="phone-type">
<xsd:sequence>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:element name="number" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
例6-9は、EclipseLinkでこのマッピングを取得するためにJavaクラスに注釈を付ける方法を示しています。JAXBの標準的な@XmlElement注釈をCollectionフィールドまたは配列フィールドで使用すると、これを実現できます。
例6-9 @XmlElement注釈の使用
package example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlElement(name="first-name")
private String firstName;
@XmlElement(name="last-name")
private String lastName;
@XmlElement(name="phone-number")
private List<PhoneNumber> phoneNumbers;
...
}
package example;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
@XmlAttribute
private String type;
private Integer number;
...
}
例6-10は、EclipseLinkのOXMメタデータ形式でマッピング情報を定義する方法を示しています。
例6-10 XMLマッピングのサンプル
...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-element java-attribute="firstName" name="first-name" type="java.lang.String"/>
<xml-element java-attribute="lastName" name="last-name" type="java.lang.String"/>
<xml-element java-attribute="phoneNumbers" name="phone-number" type="PhoneNumber" container-type="java.util.ArrayList"/>
</java-attributes>
</java-type>
<java-type name="PhoneNumber">
<java-attributes>
<xml-attribute java-attribute="type" type="java.lang.String"/>
<xml-value java-attribute="number" type="java.lang.Integer"/>
</java-attributes>
</java-type>
...
Collectionの要素がグループ化要素の内側に表示されるようにするために、@XmlElementWrapperを使用できます。
例6-11 @XmlElementWrapper注釈の使用
package example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlElement(name = "phone-number")
@XmlElementWrapper(name="phone-numbers")
private List<PhoneNumber> phoneNumbers;
...
}
これにより、次のXMLが生成されます。
<customer>
<first-name>Bob</first-name>
<last-name>Smith</last-name>
<phone-numbers>
<phone-number type="Home">
<number>5559827222</number>
</phone-number>
<phone-number type="Work">
<number>5558872216</number>
</phone-number>
</phone-numbers>
</customer>