1

これが課題です...

同じモデルに基づく複雑な分散システムがあります

次のようになります。

A <-(XML)-> B <-(JSON)-> C

A、B、C は基本的に同じモデルに基づく異なるアプリケーションであるため、別の Java (Maven) プロジェクトでモデルを維持することにしました。

  • 各アプリケーションは永続化のために JPA を使用します
  • 各アプリケーションは、エンティティ属性のサブセットのみを使用して保持します
  • データ交換フォーマットは同じモデル (XML または MOXy を使用した JSON) に基づいています。
  • エンティティ属性のサブセットのみを使用する 2 つの交換フォーマットがあります。

エンティティのより技術的な例 (疑似コード) を次に示します。

class Foo {
  a;
  ab;
  bc;
  c;
  ac;
  // ...
}

ここで、a はアプリケーション A で使用され、ab はアプリケーション A とアプリケーション B で使用され、bc はアプリケーション B と C で使用されます。

交換フォーマットの同じ要件。

それを実装する方法はありますか?

よろしくお願いします。

編集: その問題のおそらく最善の解決策は、グローバル モデルから異なるクラスを自動生成することです。上記の例からエンティティを取得すると、これは次のようになります。

アプリケーション A:

class Foo {
  a;
  ab;
  ac;
  // ...
}

アプリケーション B:

class Foo {
  ab;
  bc;
  // ...
}
4

2 に答える 2

2

EclipseLink 2.5.0 を使用している場合は、このユース ケースに MOXy の@XmlNamedObjectGraphs拡張機能を利用できます。EclipseLink 2.5.0 リリース候補は、次のリンクからダウンロードできます。

ドメイン モデル (Foo)

この@XmlNamedObjectGraph拡張機能を使用すると、マーシャリングとアンマーシャリングで使用できるマッピングのサブセットを指定できます。

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

@XmlNamedObjectGraphs({ 
    @XmlNamedObjectGraph(
        name="a",
        attributeNodes={
            @XmlNamedAttributeNode("a"),
            @XmlNamedAttributeNode("ab"),
            @XmlNamedAttributeNode("ac")
        }
    ),
    @XmlNamedObjectGraph(
        name="b",
        attributeNodes={
            @XmlNamedAttributeNode("ab"),
            @XmlNamedAttributeNode("bc")
        }
    ),
    @XmlNamedObjectGraph(
        name="c",
        attributeNodes={
            @XmlNamedAttributeNode("bc"),
            @XmlNamedAttributeNode("c"),
            @XmlNamedAttributeNode("ac")
        }
    )

})
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    int a;
    int ab;
    int bc;
    int c;
    int ac;

}

デモ

Foo以下のデモ コードでは、定義したオブジェクト グラフを利用して の1 つのインスタンスを作成し、4 つの異なる方法で出力します。

import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        Foo foo = new Foo();
        foo.a = 1;
        foo.ab = 2;
        foo.ac = 3;
        foo.bc = 4;
        foo.c = 5;

        // Marshal to XML - Everything
        marshaller.marshal(foo, System.out);

        // Marshal to XML - Application A
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, "a");
        marshaller.marshal(foo, System.out);

        // Marshal to JSON - Application B
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, "b");
        marshaller.marshal(foo, System.out);

        // Marshal to JSON - Application C
        marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, "c");
        marshaller.marshal(foo, System.out);
    }

}

出力

以下は、デモ コードから生成した 4 つの異なるビューです。Foo同じデータを入力して、毎回まったく同じインスタンスをマーシャリングしたことを思い出してください。

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <a>1</a>
   <ab>2</ab>
   <bc>4</bc>
   <c>5</c>
   <ac>3</ac>
</foo>
<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <a>1</a>
   <ab>2</ab>
   <ac>3</ac>
</foo>
{
   "foo" : {
      "ab" : 2,
      "bc" : 4
   }
}{
   "foo" : {
      "bc" : 4,
      "c" : 5,
      "ac" : 3
   }
}

詳細については

于 2013-05-08T16:48:59.363 に答える
1

モデルが大きく異なる場合は、モデルが異なるだけでなく、継承を使用する可能性もあります。

JPA の場合、orm.xml でマッピングを定義し、必要に応じてマッピングすることを選択できるため、アプリケーションごとに異なる orm.xml を持つだけで、同じモデルを使用できます。

于 2013-05-08T14:11:56.120 に答える