EclipseLink - JPA和MOXy - 对同一数据模型的不同视图

时间:2013-05-08 10:08:10

标签: java java-ee eclipselink moxy

这是挑战......

我有一个基于相同模型的复杂分布式系统

看起来像这样:

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

A,B和C是基于相同模型的基本的不同应用程序,因此我决定将该模型保存在单独的Java(Maven)项目中。

  • 每个应用程序都使用JPA进行持久性
  • 每个应用程序仅使用
  • 子集
  • 数据交换格式基于相同的模型(带有MOXy的XML或JSON)
  • 有两种交换格式使用仅实体属性的子集

以下是实体(伪代码)的更多技术示例:

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;
  // ...
}

2 个答案:

答案 0 :(得分: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的一个实例,然后以四种不同的方式输出它,利用我们定义的对象图。

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

}

<强>输出

以下是我们从演示代码中生成的四种不同视图。请记住,我们每次使用相同的数据编组完全相同的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
   }
}

了解更多信息

答案 1 :(得分:1)

如果模型非常不同,可能只是拥有不同的模型,或者可能使用继承。

对于JPA,您可以在orm.xml中定义映射并选择映射您希望的映射,这样您就可以使用相同的模型,只为每个应用程序使用不同的orm.xml。