IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  XML  >

リレーショナル・データベースでの XML のオプション要素: 第 2 回 JAXB と Java アノテーションを使用して XML のオプション・データを作成、保管、操作する

XML で定義されたオプション・データをリレーショナル・データベースに格納する

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

ダウンロード

原文はこちら

原文はこちら


レベル: 中級

Stephen B Morris, CTO, Omey Communications

2009年 7月 07日

2 回連載の第 2 回目となるこの記事では、XML のオプション・リレーショナル・データの作成、保管、操作にはどのようなソフトウェアが必要であるかを詳しく調べます。使用するソフトウェアには、JAXB (Java™ Architecture for XML Binding) によって完全に変換されたサンプル・コード、JPA (Java Persistence API)/Hibernate、メモリー内データベース、そして永続化に関連するアノテーションなどが含まれています。
連載のその他の記事

この 2 回連載記事の第 1 回では、JAXB を使って XML ドメインから Java コードに変換する方法を説明しました。このドメイン間変換という概念は、多くの研究分野で役に立ちます。その一例としては、信号処理の分野での時間ドメインから周波数ドメインへの変換が挙げられます。XSLT での変換もこれに関連する例として挙げられ、XSLT ではスタイルシートを使用して XML を他のテキスト・フォーマット (HTML など) に変換します。それではまず、JAXB に必要なセットアップから見ていきましょう。

JAXB のセットアップ

普段、私はソフトウェアのインストールについてはあまり触れませんが、Java Web Services Developer Pack (「参考文献」を参照) をインストールするときには、いつも以上に注意が必要です。そのため、皆さんがすべてをきちんとインストールできるように、インストール・プロセスについて説明しておきます。

まず始めに、バージョン 2.0 のパッケージをダウンロードします。この Web サービス・ダウンロードのサイズは比較的小さいので (23MB)、ダウンロードにはそれほど時間がかからないはずです。この記事を読んだ後、さらに詳細を調べたいのであれば、Web サービス・ドキュメンテーション・パッケージもダウンロードしてください (同じページにあります)。InstallShield ウィザードを実行するには、ダウンロードした実行可能ファイルをダブルクリックします。その後は、ウィザードの指示に従います。私は Web コンテナーのインストールを選択しませんでした。また、インストール・ディレクトリーは C:\Sun\jwsdp-2.0 に変更しました。

よく使われる頭字語
  • API: Application Programming Interface
  • HTML: Hypertext Markup Language
  • SQL: Structured Query Language
  • XML: Extensible Markup Language
  • XSD: XML Schema Definition
  • XSLT: Extensible Stylesheet Language Transformation

ダウンロードをインストールした後には、極めて重要な作業が待っています。%JAVA_HOME%\jre\lib ディレクトリーのなかに、endorsed という名前を付けたフォルダーを作成してください。次に、C:\Sun\jwsdp-2.0\lib フォルダーの中身を新規に作成したフォルダー %JAVA_HOME%\jre\lib\endorsed に貼り付けます。%JAVA_HOME% 環境変数は、Java ソフトウェア開発キット (JDK) インストールへの絶対パスです。お望みであれば、コマンドラインで java.endorsed.dirs システム・プロパティーを使用することもできますが、新しくディレクトリーを作成する方がいくらか簡単です。

もう 1 つ必要な作業は、Apache Ant をコピーすることです (「参考文献」を参照)。Ant をダウンロードしてインストールし、実行可能プログラムがシステム PATH に設定されていることを確認してください。

ソース・コードの実行

この記事のソース・コードは、「ダウンロード」に .zip ファイルとして含まれています。記事の例に従うには、このファイルの内容を C:\article_code などのフォルダーに解凍してください。すると、このディレクトリーの下に 2 つのフォルダーが作成されます。1 つは unmarshal-read、もう 1 つは dbcode という名前のフォルダーです。




上に戻る


JAXB サンプルの実行

環境が適切に構成されていることを確認するには、サンプル・フォルダーのいずれか (例えば、C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read など) で DOS コンソールを開きます。このフォルダーで、リスト 1 に示すように Ant ターゲットを実行してみてください。


リスト 1. Ant の実行
	
C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read>ant -p
Buildfile: build.xml
This sample application demonstrates how to unmarshal 
an instance document into a Java content tree and access 
data contained within it.
			
Main targets:
clean    Deletes all the generated artifacts.
compile  Compile all Java source files
javadoc  Generates javadoc
run      Run the sample app
Default target: run

リスト 1 のようなプログラム出力が表示されたら、セットアップは正常に行われています。ちなみに、ant -p コマンドは、特定の build.xml ファイルでサポートされているターゲットを判断する上で重宝するコマンドです。このコマンドを使用すれば、ターゲットを実行しなくてもビルド・スクリプトの内容を見ることができます。

サンプル・プログラムを実行するには、何もパラメーターを指定せずに ant コマンドを入力します。すると、リスト 2 のプログラム出力が表示されます。


リスト 2. JAXB サンプル・プログラムの実行
	
C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read>ant
Buildfile: build.xml
compile:
[echo] Compiling the schema...
[xjc] C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read\gen-src\primer.po is not 
found and thus excluded from the dependency check [xjc] Compiling file:/C:/Sun/jwsdp-2.0/jaxb/samples/unmarshal-read/po.xsd [xjc] Writing output to C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read\gen-src [echo] Compiling the java source files... [javac] Compiling 4 source files to C:\Sun\jwsdp-2.0\jaxb\samples\unmarshal-read\classes run: [echo] Running the sample application... [java] Ship the following items to: [java] Alice Smith [java] 123 Maple Street [java] Cambridge, MA 12345 [java] US [java] [java] 5 copies of "Nosferatu - Special Edition (1929)" [java] 3 copies of
"The Mummy (1959)" [java] 3 copies of "Godzilla and Mothra: Battle for Earth/Godzilla vs. King Ghidora" BUILD SUCCESSFUL Total time: 9 seconds

リスト 2 には完全な JAXB プログラムが記載されています。この後すぐに、この JAXB プログラムを使って XML を Java コードに変換する例を紹介します (ここでは用語が重要になるので、用語について説明しておきます。XML を Java コードにアンマーシャリングすると言いますが、マーシャリングとは Java コードを XML に変換すること、そしてアンマーシャリングとは XML を Java コードに変換することです)。次は、オプション要素が含まれる XML データについて見て行きます。




上に戻る


オプション要素が含まれる XSD 仕様

リスト 3xsd:complexType 要素を記載します。これがこの記事で検討する要素です。


リスト 3. オプション要素が含まれる XSD の型定義
	
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="EuropeanAddress"/>
<xsd:element name="billTo" type="EuropeanAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>

リスト 3 のコードは po.xsd という名前のファイルの一部で、このファイルはこれから説明する XML のスキーマです。リスト 4 に、po.xsd スキーマに従った XML ファイル (po.xml) を記載します。


リスト 4. XML 文書の例
	
<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
    <shipTo country="IE">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <city>Cambridge</city>
        <postcode>12345>/postcode>
    </shipTo>
    <billTo country="IE">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Cambridge</city>
        <postcode>12345</postcode>
    </billTo>
    <items>
      <item partNum="242-NO" >
         <productName>Nosferatu - Special Edition 
(1929)>/productName>
         <quantity>5</quantity>
         <USPrice>19.99</USPrice>
       </item>
      <item partNum="242-MU" >
         <productName>The Mummy (1959)</productName>
         <quantity>3</quantity>
         <USPrice>19.98</USPrice>
       </item>
      <item partNum="242-GZ" >
         <productName>Godzilla and Mothra: Battle for 
Earth/Godzilla vs. King Ghidora</productName>
         <quantity>3</quantity>
         <USPrice>27.95</USPrice>
       </item>
   <>/items>
</purchaseOrder>

リスト 4 の XML にはコメント・フィールドが 1 つも含まれていないことに注意してください。リスト 3 に示されているように、コメント・フィールドはオプションです。

ここで、リスト 4 の XML データを 1 つ以上の Java クラスにアンマーシャリングします。それには DOS コンソールを unmarshal-read というソース・コード・フォルダーで開き、以下のコマンドを実行します。

ant compile -Djwsdp.home=C:\Sun\jwsdp-2.0

リスト 5 に、予想される出力を記載します。


リスト 5. XML から Java への変換
	
C:\article_code\unmarshal-read>ant compile -
Djwsdp.home=C:\Sun\jwsdp-2.0
Buildfile: build.xml

compile:
     [echo] Compiling the schema...
    [mkdir] Created dir: C:\article_code\unmarshal-
read\gen-src
      [xjc] C:\article_code\unmarshal-read\gen-
src\primer.po is not found and thus excluded from the 
dependency check
      [xjc] Compiling file:/C:/article_code/unmarshal-
read/po.xsd
      [xjc] Writing output to C:\article_code\unmarshal-
read\gen-src
     [echo] Compiling the java source files...
    [mkdir] Created dir: C:\article_code\unmarshal-
read\classes
    [javac] Compiling 5 source files to 
C:\article_code\unmarshal-read\classes

BUILD SUCCESSFUL
Total time: 5 seconds

リスト 5 では、JAXB が魔法のように XML ファイルから Java クラスを生成しています。このプロセスを実行しているのが、リスト 6 の Java プログラムです。


リスト 6. アンマーシャリング・プロセスを実行するコード
	
public static void main( String[] args ) {
        try {
            // create a JAXBContext capable of handling classes generated into
            // the primer.po package
            JAXBContext jc = JAXBContext.newInstance( "primer.po" );

            // create an Unmarshaller
            Unmarshaller u = jc.createUnmarshaller();

            // unmarshal a po instance document into a tree of Java content
            // objects composed of classes from the primer.po package.
            JAXBElement<?> poElement =
      (JAXBElement<?>)u.unmarshal( new FileInputStream( "po.xml" ) );
            PurchaseOrderType po = (PurchaseOrderType)poElement.getValue();

            // examine some of the content in the PurchaseOrder
            System.out.println( "Ship the following items to: " );

            // display the shipping address
            EuropeanAddress address = po.getShipTo();
            displayAddress( address );

            // display the items
            Items items = po.getItems();
            displayItems( items );

        } catch( JAXBException je ) {
            je.printStackTrace();
        } catch( IOException ioe ) {
            ioe.printStackTrace();
        }
    }

リスト 6 のコードは、以下の主要なステップで構成されています。

  1. JAXB コンテキストを作成する
  2. そのコンテキストを使用してアンマーシャラーを作成する
  3. po.xml ファイルをアンマーシャリングする
  4. PurchaseOrderType クラスのオブジェクトを作成する
  5. そのオブジェクトからいくつかの要素を抽出して表示する

以上のように、リスト 6 のコードにはかなりの処理内容が詰まっています。元の XML データの Java 表現が用意できたところで、次はこのデータをリレーショナル・データベースに格納します。




上に戻る


Java コードからデータベース・エンティティーへの変換

Java アノテーションがその本領を発揮するのは、Java クラスを永続化させるときです。このような Java コードからリレーショナル・ドメインへのマッピングは、オブジェクト・リレーショナル・マッピング (ORM) と呼ばれます。リスト 7 に、ShippingAddress クラスのマッピング例を記載します。


リスト 7. ShippingAddress の ORM
	
@Embeddable
public class ShippingAddress {

    @Column(name = "SHIPPING_ADDRESS_STREET")
    private String street;

    @Column(name = "SHIPPING_ADDRESS_CITY")
    private String city;

    ShippingAddress() {}

    public ShippingAddress(String street, String city) {
        this.street = street;
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    private void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    private void setCity(String city) {
        this.city = city;
    }
}

リスト 7 を見ると、アノテーションのことをひとまず忘れるとしたら、これは ShippingAddress という名前の単純な Java クラスでしかありません。実際、Eclipse などの統合開発環境 (IDE) を使用すれば、リスト 7 のコードの大部分 (つまり、コンストラクターと、セッターおよびゲッター・メソッドの部分) を自動的に生成するのは簡単です。アノテーションは単に、クラスとそのプロパティーをリレーショナル・ドメインにマッピングするためだけに使用されます。上記の例では、@Embeddable アノテーションによって、このクラス全体を別のクラス (リスト 8 の entity クラス) に組み込めることが示されています。


リスト 8. entity クラス
	
@Entity
@Table(name = "PURCHASE_ORDERS")
public class PurchaseOrder {

    @Id @GeneratedValue
    @Column(name = "PO_ID")
    private Long id;

    @Embedded
    private ShippingAddress shippingAddress;
    @Embedded
    private BillingAddress billingAddress;

    @Column(name = "COMMENT")
    private String comment;
    @Column(nullable=false, name="COMMENT_ENTERED", 
columnDefinition="boolean default false")
    private boolean commentEntered;

// More methods here
}

リスト 8ShippingAddress クラスのインスタンスを PurchaseOrder クラスに組み込んでいる方法に注目してください。この entity クラスが一体どのようにしてデータベースと結び付くのでしょうか。




上に戻る


データベース・コードの実行

データベース・コードを実行するには、DOS コンソールを dbcode フォルダーで開きます。次に start コマンドを入力して、さらに 2 つの DOS コンソールを作成します。そして DOS コンソールのいずれか 1 つで、ant startdb と入力することで Ant ターゲット を実行します。

このターゲットはメモリー内 HSQLDB (HyperSQL DataBase) を起動します。このコマンドの実行が完了すると、リスト 9 のような出力が表示されるはずです。


リスト 9. HSQLDB の実行
	
C:\article_code\dbcode>ant startdb
Buildfile: build.xml

startdb:
     [java] [Server@1e0be38]: [Thread[main,5,main]]: checkRunning(false) 
entered
     [java] [Server@1e0be38]: [Thread[main,5,main]]: checkRunning(false) exited
     [java] [Server@1e0be38]: Startup sequence initiated from main() method
     [java] [Server@1e0be38]: Loaded properties from 
[C:\article_code\dbcode\server.properties]
     [java] [Server@1e0be38]: Initiating startup sequence...
     [java] [Server@1e0be38]: Server socket opened successfully in 62 ms.
     [java] [Server@1e0be38]: Database [index=0, id=0, db=file:database/db, 
alias=] opened successfully in 313 ms.
     [java] [Server@1e0be38]: Startup sequence completed in 375 ms.
     [java] [Server@1e0be38]: 2009-04-10 09:54:26.625 HSQLDB server 1.8.0 is 
online
     [java] [Server@1e0be38]: To close normally, connect and execute SHUTDOWN 
SQL
     [java] [Server@1e0be38]: From command line, use [Ctrl]+[C] to abort 
abruptly

リスト 9 の Ant ターゲットを実行した後は、データベース・マネージャーが実行中になりますが、データベースはまだありません。そこで次の作業として、Ant ターゲット schemaexport を実行して、リスト 10 のデータベース・スキーマを作成します。


リスト 10. データベースの作成
	
C:\article_code\dbcode>ant schemaexport
Buildfile: build.xml

compile:
    [mkdir] Created dir: C:\article_code\dbcode\build
    [javac] Compiling 4 source files to C:\article_code\dbcode\build

copymetafiles:
     [copy] Copying 2 files to C:\article_code\dbcode\build

schemaexport:
[hibernatetool] Executing Hibernate Tool with a JPA Configuration
[hibernatetool] 1. task: hbm2ddl (Generates database schema)
[hibernatetool]
[hibernatetool]     drop table PURCHASE_ORDERS if exists;
[hibernatetool]
[hibernatetool]     create table PURCHASE_ORDERS (
[hibernatetool]         PO_ID bigint generated by default as identity (start 
with 1),
[hibernatetool]         SHIPPING_ADDRESS_STREET varchar(255),
[hibernatetool]         SHIPPING_ADDRESS_CITY varchar(255),
[hibernatetool]         BILLING_ADDRESS_STREET varchar(255),
[hibernatetool]         BILLING_ADDRESS_CITY varchar(255),
[hibernatetool]         COMMENT varchar(255),
[hibernatetool]         COMMENT_ENTERED boolean default false not null,
[hibernatetool]         primary key (PO_ID)
[hibernatetool]     );

BUILD SUCCESSFUL
Total time: 8 seconds

リスト 10 の SQL 文、create table PURCHASE_ORDERS に注目してください。これで常駐データベースは用意できたので、Ant ターゲット run を実行することで、このデータベースにデータを挿入することができます。したがって、3 つ目の DOM コンソールでは ant run コマンドを実行します (リスト 11 を参照)。


リスト 11. プログラムの実行
	
C:\article_code\dbcode>ant run
Buildfile: build.xml

compile:

copymetafiles:

run:
     [java] Value of CommentEntered false
     [java] 1 purchase order(s) found:
     [java] Broad Street
     [java] Boston
     [java] Comment entered: true

BUILD SUCCESSFUL
Total time: 3 seconds

リスト 11 には、データベースに正常にデータが入力されたことが示されています。データベースの内容を確認するには、ant dbmanager コマンドを実行します (別の DOS コンソールから実行してください)。このコマンドによって、図 1 のようなウィンドウが表示されます。


図 1. データベース・マネージャー・アプリケーション

図 1 の単純なグラフィカル・データベース・マネージャー・アプリケーションは、前のステップで作成したデータベースに接続します。データベースに対してクエリーを実行するには、Command > SELECT の順にクリックし、以下の SQL 文を入力してください。

SELECT * FROM PURCHASE_ORDERS

これで Execute SQL をクリックすると、図 2 のような内容が表示されます。


図 2. データが入力されたデータベース

図 2 に示されているデータベース列をリスト 6 およびリスト 7 と比較すると、実際に Java コードの内容がデータベースに組み込まれていることがわかります。これはもちろん、ORM 技術のおかげです。現在、図 2 のデータベースには 2 行のデータが含まれています。リスト 12 に、この 2 行のデータを作成する Java コードを記載します。


リスト 12. 2 つのオブジェクトの永続化
	
PurchaseOrder purchaseOrder = new PurchaseOrder();
purchaseOrder.setShippingAddress(new ShippingAddress("Broad Street", 
"Boston"));
purchaseOrder.setBillingAddress(new BillingAddress("Broad Street", "Boston"));
purchaseOrder.setComment("A COMMENT");
purchaseOrder.setCommentEntered(true);

PurchaseOrder purchaseOrder1 = new PurchaseOrder();
purchaseOrder1.setShippingAddress(new ShippingAddress("Broader Street", "New 
York"));
purchaseOrder1.setBillingAddress(new BillingAddress("Broader Street", "New 
York"));

em.persist(purchaseOrder);
em.persist(purchaseOrder1);

リスト 12 のコードでは、PurchaseOrder クラスの 2 つのオブジェクトをインスタンス化します。この 2 つのオブジェクトにデータが入力されたら、em.persist() を呼び出してオブジェクトをデータベースに永続化させています。注意する点として、purchaseOrder オブジェクトには明示的にコメントを挿入していますが、purchaseOrder1 にはコメントがありません。これを念頭に図 2 を見てみると、COMMENT 列のエントリーが null となっている行があります。しかし、対応する COMMENT_ENTERED 列が NULL 値になることは決してありません。この列は True または False のいずれかとなります。

これで、特定の行にコメントが含まれるかどうかを判断するときに、COMMENT 列に NULL 値があるかどうかを調べる必要はなくなりました。代わりに COMMENT_ENTERED 列の値を読み取って、値が True であれば、COMMENT 列に値が含まれていることがわかります。つまり、XML のオプション・データは適切にモデル化されて実装されたということです。




上に戻る


まとめ

XML データからリレーショナル・データに移行するのは複雑なことのように思えるかもしれませんが、その手順はまず XSD および XML ファイルを処理することから始め、これらのファイルを JAXB を使用して対応する Java クラスに変換し、続いて ORM 技術によってデータベースにデータを入力する、たったそれだけのことです。

明らかに、この記事での問題領域はかなり小さいですが、平均的なサイズのエンタープライズ・アプリケーションにスケール・アップした場合には XML オブジェクトが相当な数になるのが通常です。これらのオブジェクトはビジネス・ドメインのオブジェクトなので、XML で定義するのがもちろん理にかなっています。それは 1 つには、XML で定義する場合、プログラマーでなくてもオブジェクトを定義できるからです。そしてもう 1 つの大きな利点として、オブジェクトを XML で定義すると、JAXB を使用して XML を Java エンティティーに完璧に変換することができます。

XML オブジェクトが Java ドメインに変換されると、アノテーションの威力が発揮され、Java クラスに最小限の変更を加えるだけで永続エンティティーにすることができます。そこからは、データをリレーショナル・データベースに取り込むだけの話です。

Java オブジェクト・リレーショナル・アノテーションを巧みに使用することで、簡潔なスキーマ定義の生成に役立ちます。巧みに使用するとはつまり、nullable=false などのアノテーション要素を賢明に使用して、選択された項目だけを「NULL 可能」にするということです。そして COLUMN_ENTERED 値と組み合わせれば、NULL 値が挿入される心配はありません。これは、実際に有効な設計です。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Source code for this articlecode.zip5700KBHTTP
ダウンロード形式について


参考文献

学ぶために
  • リレーショナル・データベースでの XML のオプション要素: 第 1 回 NULL 値は果たして必要か」(Stephen B. Morris 著、developerWorks、2009年6月): XML のオプション要素に備えた計画で、データベース内の NULL 値を避けてください。この記事では、XML ファイル内に現れることもあれば、現れないこともある XML のオプション要素を、他への影響が少ない方法で処理する代替手段を説明しています。

  • JPA: Sun の JPA ウィキにアクセスして、Java EE プラットフォームでのパーシスタンスおよびオブジェクト/リレーショナル・マッピングに対応する Java Persistence API について詳しく学んでください。

  • IBM XML 認定: XML や関連技術の IBM 認定技術者になる方法について調べてください。

  • XML Technical library: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM Redbooks については、developerWorks XML ゾーンを参照してください。

  • technology bookstore: この記事で紹介した技術やその他の技術に関する本を参照してください。

  • developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。

  • developerWorks podcasts: ソフトウェア開発者向けの興味深いインタービューとディスカッションを聞いてください。


製品や技術を入手するために
  • Java Web Services Developer Pack 2.0: この開発用パックをダウンロードして、この記事で説明した JAXB 変換機能をさらに深く理解してください。

  • Apache Ant:Java クラスと XML を使用するビルド・ツール、Apache Ant をダウンロードしてください。

  • IBM 製品の評価版: DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を体験するには、IBM SOA Sandbox のオンライン試用版をダウンロードするか、検討してみてください。


議論するために


著者について

Stephen Morris は、アイルランドを拠点とするフリーランス・ライター兼コンサルタントです。エンタープライズ開発とネットワーク・アプリケーションに幅広い経験を持つ彼は、これまでネットワークを専門とする世界最大規模の企業に協力し、J2EE/J2SE ベースのネットワーク管理システム、課金アプリケーション、金融システム、SNMP エンティティーの移植/開発、ネットワーク・デバイス技術、そしていくつかのモバイル・コンピューティング・アプリケーションなどのプロジェクトに取り組みました。彼はコンピューター・サイエンスで修士号を取得し、ネットワーク管理の分野で 3 つの特許を持っています。著書に『Moving Your Career Up the Value Chain: Building Specialized Development Skills in a Global Economy』がある他、ネットワーク管理やその他の話題に関する数々の記事も書いています。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ