ヘッダーをスキップ
Oracle® Fusion Middleware Oracle TopLinkによるJAXBアプリケーションの開発
12c (12.1.2)
E48003-01
  目次へ移動
目次

前
 
次
 

5 特殊なスキーマ・タイプのマッピング

この章の内容は次のとおりです。

5.1 日付および時刻のマッピング

@XmlSchemaType注釈を使用して、日付および時刻の情報のXML表示をカスタマイズできます。また、EclipseLink MOXyでは、JAXB仕様(JSR-222)で扱われていない次の型がサポートされています。

次のXMLスキーマには、xsd:date型のdate-of-birth要素が含まれています。

例5-1 XMLスキーマのサンプル

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:element name="customer">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="date-of-birth" type="xsd:date" minOccurs="0"/>
         </xsd:sequence>
      </xsd:complexType>
   </xsd:element>
</xsd:schema>
 

5.1.1 生成されたモデルの理解

JAXB XML Schema to Javaコンパイラ(XJC)を使用して、サンプル・スキーマからクラス・モデルを生成できます。次に例を示します。

> xjc -d output-dir -p example date.xsd
 

これにより、次のCustomerクラスが生成されます。

例5-2 Customerクラスのサンプル

package example;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"dateOfBirth"})
@XmlRootElement(name = "customer")
public class Customer {
 
    @XmlElement(name = "date-of-birth")
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar dateOfBirth;
 
    public XMLGregorianCalendar getDateOfBirth() {
        return dateOfBirth;
    }
 
    public void setDateOfBirth(XMLGregorianCalendar value) {
        this.dateOfBirth = value;
    }
 
}
 

次の点に注意してください。

  • dateOfBirthプロパティの型はjavax.xml.datatype.XMLGregorianCalendar

  • dateOfBirthプロパティは@XmlSchemaType注釈を使用

Javaの一部のデータ型(XMLGregorianCalendarなど)には、複数のXML表現(xsd:datexsd:timexsd:dateTimeなど)があります。@XmlSchemaTypeを使用して適切な表現を選択します。

5.1.2 異なるDate(またはCalendar)プロパティの使用

デフォルトでは、JAXB XML schema to Javaコンパイラ(XJC)によって、XMLGregorianCalendar型のプロパティが生成されます。ただし、例5-3に示すように、これは、java.util.Dateまたはjava.util.Calendarに簡単に変更できます。

例5-3 java.util.Dateの使用

package blog.date;
 
import java.util.Date;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "customer")
public class Customer {
 
    @XmlElement(name = "date-of-birth")
    @XmlSchemaType(name = "date")
    protected Date dateOfBirth;
 
    public Date getDateOfBirth() {
        return dateOfBirth;
    }
 
    public void setDateOfBirth(Date value) {
        this.dateOfBirth = value;
    }
 
}

5.2 unionフィールドへのマッピング

次のXMLスキーマとクラス図は、XMLスキーマの結合の代表的な用途を示しています。

例5-4 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="shoe-size" type="size-type" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:simpleType name="size-type">
        <xsd:union memberTypes="xsd:decimal xsd:string" />
    </xsd:simpleType>
</xsd:schema>
 

図5-1 unionフィールドへのマッピング

unionフィールドへのマッピング
「図5-1 unionフィールドへのマッピング」の説明

図5-2に、XML文書内のunionフィールドへのマッピングを示します。このXML文書はこの例のスキーマに準拠しています。EclipseLinkでXML文書をアンマーシャリングする場合、正常な変換が行われるまで、union型のそれぞれが試行されます。unionにおける最初のスキーマ・タイプはxsd:decimalです。10.5は有効な10進数であるため、EclipseLinkはその値を適切な型に変換します。

図5-2 XML文書内にあるunionフィールドへのマッピング

XML文書内にあるunionフィールドへのマッピング
「図5-2 XML文書内にあるunionフィールドへのマッピング」の説明

図5-3では、値Mは、有効なxsd:decimal型ではないため、次のunion型であるxsd:stringが試行されます。

図5-3 unionフィールドへのマッピング

unionフィールドへのマッピング
「図5-3 unionフィールドへのマッピング」の説明

現時点では、EclipseLinkは、注釈またはOXMメタデータを使用したunionのマッピングをサポートしていません。ただし、EclipseLinkのXMLカスタマイザを使用してマッピングを作成することはできます。

最初に、shoeSize属性に@XmlTransientという注釈を付けて、そのマッピングが自動的に生成されないようにします。また、@XmlCustomizer注釈も付けます。こうすると、CustomerCustomizerクラスによって、コード内にunionマッピングが作成されます。

例5-5 EclipseLinkのカスタマイザの使用

package example;
 
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlCustomizer(CustomerCustomizer.class)
public class Customer {
   @XmlTransient
   private Object shoeSize;
 
   ...
}
 

CustomerCustomizerクラスを使用すると、shoeSize属性にマッピングを手動で追加できます。例5-6では、マッピング上にXMLUnionFieldが構成されており、addSchemaType()を呼び出すことによって、可能なunionメンバー・タイプが追加されます。

例5-6 unionフィールドのマッピング

package example;
 
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.oxm.*;
 
public class CustomerCustomizer implements DescriptorCustomizer {
 
   @Override
   public void customize(ClassDescriptor descriptor) throws Exception {
      XMLDirectMapping shoeSizeMapping = new XMLDirectMapping();
      shoeSizeMapping.setAttributeName("shoeSize");
 
      XMLUnionField shoeSizeField = new XMLUnionField();
      shoeSizeField.setXPath("shoe-size/text()");
      shoeSizeField.addSchemaType(XMLConstants.DECIMAL_QNAME);
      shoeSizeField.addSchemaType(XMLConstants.STRING_QNAME);
 
      shoeSizeMapping.setField(shoeSizeField);
 
      descriptor.addMapping(shoeSizeMapping);
   }
 
}
 

5.2.1 変換順の理解

addSchemaType()の呼出し順は重要です。XMLの値をJavaに変換する際、EclipseLinkは、フィールドに追加された順に変換を試行し、正常な変換が行われるとすぐに戻ります。たとえば、10.5shoeSizeをアンマーシャリングするとします。

...
shoeSizeField.addSchemaType(XMLConstants.DECIMAL_QNAME);
shoeSizeField.addSchemaType(XMLConstants.STRING_QNAME);
...
 

BigDecimalが作成され、値が格納されます。ただし、XMLUnionFieldが次のように設定された場合は異なります。

...
shoeSizeField.addSchemaType(XMLConstants.STRING_QNAME);
shoeSizeField.addSchemaType(XMLConstants.DECIMAL_QNAME);
...
 

この場合は、shoeSizeの値はString("10.5")となります。

5.2.2 変換クラスのカスタマイズ

EclipseLinkでは、一連のデフォルトの変換を使用して、Java属性の値を作成します(この場合は、xsd:decimalBigDecimalに変換されます)。XMLUnionFieldメソッドaddConversionを使用して、Javaコードにおけるこの動作をオーバーライドできます。たとえば、JavaオブジェクトによってshoeSizeFloatとして格納する場合は、次のようにします。

shoeSizeField.addConversion(XMLConstants.DECIMAL_QNAME, Float.class);

5.3 バイナリ型

byte[]Byte[]などのバイナリ型フィールドにマッピングする際には、これ以外にも検討すべき項目があります。

5.3.1 バイナリのBase64形式およびHex形式の指定

EclipseLinkでは、base64Binary(デフォルト)とhexBinaryという、2つの表現形式でのバイナリ・データのマーシャリングおよびアンマーシャリングをサポートしています。EclipseLink OXMで@XmlSchemaType注釈または<xml-schema-type>要素を使用して、目的のバイナリ形式を指定できます。次の例は、これらの形式のそれぞれに対して同じbyte[]をマーシャリングした結果を示しています。

例5-7 注釈

package example;
 
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class BinaryData {
 
   @XmlSchemaType(name="hexBinary")
   public byte[] hexBytes;
 
   @XmlSchemaType(name="base64Binary")
   public byte[] base64Bytes;
 
}
 

例5-8 EclipseLink OXM

...
<java-type name="example.BinaryData">
    <xml-root-element/>
    <java-attributes>
        <xml-element java-attribute="hexBytes">
            <xml-schema-type name="hexBinary"/>
        </xml-element>
        <xml-element java-attribute="base64Bytes">
            <xml-schema-type name="base64Binary"/>
        </xml-element>
    </java-attributes>
</java-type>
...
 
BinaryData b = new BinaryData();
b.hexBytes = new byte[] {2,4,8,16,32,64};
b.base64Bytes = b.hexBytes;

jaxbContext.createMarshaller().marshal(b, System.out);

例5-9 出力

<?xml version="1.0" encoding="UTF-8"?>
<binaryData>
   <hexBytes>020308102040</hexBytes>
   <base64Bytes>AgMIECBA</base64Bytes>
</binaryData>
 

5.3.2 byte[]とByte[]の比較の理解

他のJavaプリミティブ/ラッパー型と異なり、EclipseLinkでは、byte[](プリミティブ)データ型とByte[](ラッパー)データ型が区別されます。次の例で示されているように、デフォルトでは、byte[]は単一の要素または属性にマーシャリングする一方、Byte[]はそれぞれのbyteをその要素としてマーシャリングします。

例5-10 byte[]とByte[]の使用

package example;
 
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class BinaryData {
 
   public byte[] primitiveBytes;
   public Byte[] byteObjects;
 
}
 
BinaryData b = new BinaryData();
b.primitiveBytes = new byte[] {34,45,56,67,78,89,89,34,23,12,12,11,2};
b.byteObjects = new Byte[] {23,1,112,12,1,64,1,14,3,2};
 
jaxbContext.createMarshaller().marshal(b, System.out);
 

例5-11 出力

<?xml version="1.0" encoding="UTF-8"?>
<binaryData>
   <primitiveBytes>Ii04Q05ZWSIXDAwLAg==</primitiveBytes>
   <byteObjects>23</byteObjects>
   <byteObjects>1</byteObjects>
   <byteObjects>112</byteObjects>
   <byteObjects>12</byteObjects>
   <byteObjects>1</byteObjects>
   <byteObjects>64</byteObjects>
   <byteObjects>1</byteObjects>
   <byteObjects>14</byteObjects>
   <byteObjects>3</byteObjects>
   <byteObjects>2</byteObjects>
</binaryData>
 

5.3.3 SOAP添付ファイルの使用

Webサービス環境でEclipseLink MOXyを使用している場合は、一部のタイプのバイナリ・データは、XMLの要素または属性に直接書き込まれるのではなく、MTOM/XOP添付ファイルとして作成されることがあります。これは、大量のバイナリ・データの最適化として行われます。

次の表は、添付ファイルとして自動的に扱われるJavaタイプを、それに対応するMIMEタイプとともに示しています。

表5-1 添付ファイルとして扱われるJava属性

Javaタイプ MIMEタイプ

java.awt.Image

image/gif

java.awt.Image

image/jpeg

javax.xml.transform.Source

text/xml

application/xml

*


javax.activation.DataHandler

*/*




注意:

SOAP添付ファイルの基本の詳細は、『Java Architecture for XML Binding (JAXB) Specification』(http://jcp.org/en/jsr/detail?id=222)の「Appendix H: Enhanced Binary Data Handling」を参照してください。


次のJavaクラスには、単純なbyte[]java.awt.Imageという2つのバイナリ・フィールドがあります。Webサービス環境では、Imageデータは添付ファイルとして自動的に作成されます。

例5-12 Javaクラスのサンプル

package example;
 
import java.awt.Image;
 
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class BinaryData {
 
   public byte[] bytes;
 
   public Image photo;
 
}
 

Webサービス環境では、例5-12に示すオブジェクトのマーシャリングは例5-13のようになります(実際の外観は、アプリケーション・サーバーのAttachmentMarshallerの実装に応じて異なります)。

例5-13 結果となるXML

<?xml version="1.0" encoding="UTF-8"?>
<binaryData>
   <bytes>Ii04Q05ZWSIXDAwLAg==</bytes>
   <photo>
      <xop:Include href="cid:1" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
   </photo>
</binaryData>
 

5.3.3.1 @XmlInlineBinaryDataの使用

バイナリ・データがインラインのstringとしてXMLに強制的に書き込まれるようにする場合は、フィールドに@XmlInlineBinaryDataという注釈を付けることができます。

例5-14 @XmlInlineBinaryData注釈の使用

package example;
 
import java.awt.Image;
 
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class BinaryData {
 
   public byte[] bytes;
 
   @XmlInlineBinaryData
   public Image photo;
 
}
 

これで、XML文書は次のようになります。

 
<?xml version="1.0" encoding="UTF-8"?>
<binaryData>
   <bytes>Ii04Q05ZWSIXDAwLAg==</bytes>
   <photo>/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHB ... Af/2Q==</photo>
</binaryData>
 

5.3.3.2 @XmlMimeTypeの使用

@XmlMimeType注釈を使用して、バイナリ・フィールドのMIMEタイプを明示的に設定できます。アプリケーションのAttachmentMarshallerAttachmentUnmarshallerは、この情報の処理を担当します。

例5-15 @XmlMimeType注釈の使用

package example;
 
import java.awt.Image;
 
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class BinaryData {
 
   public byte[] bytes;
 
   @XmlMimeType("image/gif")
   public Image photo;
 
}