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

Java EclipseLink-JPA和MOXy-同一数据模型上的不同视图,java,jakarta-ee,eclipselink,moxy,Java,Jakarta Ee,Eclipselink,Moxy,这是挑战 我有一个基于相同模型的复杂分布式系统 看起来是这样的: A <-(XML)-> B <-(JSON)-> C 其中a由应用程序a使用,ab由应用程序a使用,应用程序B由应用程序B和C使用,等等 交换格式的要求相同 你知道如何实施吗 致以最良好的祝愿 编辑: 解决这个问题的最好办法可能是从全局模型中自动生成不同的类。以上面示例中的实体为例,如下所示: A <-(XML)-> B <-(JSON)-> C 申请A: class Foo {

这是挑战

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

看起来是这样的:

A <-(XML)-> B <-(JSON)-> C
其中a由应用程序a使用,ab由应用程序a使用,应用程序B由应用程序B和C使用,等等

交换格式的要求相同

你知道如何实施吗

致以最良好的祝愿

编辑: 解决这个问题的最好办法可能是从全局模型中自动生成不同的类。以上面示例中的实体为例,如下所示:

A <-(XML)-> B <-(JSON)-> C
申请A:

class Foo {
  a;
  ab;
  ac;
  // ...
}
应用程序B:

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

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


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

如果您使用的是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
   }
}



  • 您好,谢谢您的回答。我已经考虑过了。这里的问题是,当
    A-(marshall)-(XML)-(unmarshall)->B
    时,您仍然必须在应用程序B中使用完整的模型。我的意思是,在应用程序B中仍然有相同的对象类。这意味着,您有一些未使用的属性或关系。我认为唯一的解决方案是基于一些自写的@ViewModel注释(正在工作)从全局模型中生成自定义代码(*.java文件)。不管怎样,你好,布莱斯·道格汉,谢谢你。。。那是我要找的分机。当你不得不编写客户端(webapp、Android等等)时,它是非常有用的。但是,当您希望将Java和MOXy保留在客户端时(您给出了编组示例,但没有给出解编组示例),最好从注释中自动生成客户机实体类。否则您会有一些“null”属性。。。模型不一致。在我看来,唯一的解决方案是为客户机自动生成代码(在解组端)。有没有可能在下一版本中获得此功能?JPA的东西呢?在我看来,JAXB规范(在本例中,它“只是”一个EclipseLink扩展,但无论如何)应该与JPA规范一起工作。您认为呢?@kalamar-Unmarshalling的工作方式相同,您只需在
    解组器上设置属性,而不是在
    封送器上设置属性。我可以看到我们添加了一个功能,您可以根据对象图生成一个模式,然后从中生成一个模型。JPA2.1命名了实体图,其工作原理几乎与MOXy的命名对象图相同。我们在EclipseLink MOXy中投入的一切都是为了与JPA兼容,因为EclipseLink也是JPA提供商。