JAXB / XJC 父子父导航

发布于 2024-11-15 03:13:13 字数 883 浏览 4 评论 0原文

我希望在子对象和父对象之间的类中具有双向导航方法。 IDREF 在我的情况下是不够的,因为我不想指定父级的 le id。 需要明确的是,从这样的xsd:

<complexType name="A">
    <xs:sequence>
        <element name="b" type="B" minOccurs="0" maxOccurs="unbounded"></element>
    </xs:sequence>
    <attribute name="id" type="ID"></attribute>
</complexType>
<complexType name="B">
    <attribute name="id" type="ID"></attribute>
</complexType>

我希望类看起来像这样:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }
class B {
    ...
    public A getA() {
    ...
}

并且我的xml必须看起来像这样:

<a id="a1">
    <b id="b1"/>
    <b id="b2"/>
    ...
</a>

解组后,我希望能够导航A到B并从B到A(通过b.getA) ())!! 这是一个非常基本的功能,但我没有找到一种简单的方法来实现这一点......

有什么想法吗?

提前致谢

i would like to have bidirectional navigation methods in classes between child object and parent object.
IDREF is not enough in my case because I don't want to specify le id of parent.
to be clear, from an xsd like that:

<complexType name="A">
    <xs:sequence>
        <element name="b" type="B" minOccurs="0" maxOccurs="unbounded"></element>
    </xs:sequence>
    <attribute name="id" type="ID"></attribute>
</complexType>
<complexType name="B">
    <attribute name="id" type="ID"></attribute>
</complexType>

i would like classes looks like this:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }
class B {
    ...
    public A getA() {
    ...
}

and my xml must looks like this:

<a id="a1">
    <b id="b1"/>
    <b id="b2"/>
    ...
</a>

After unmarshal, I would like to be able to navigate A to Bs AND from B to A (via b.getA()) !!
It a very basic feature, but I don't find a simple way to achieve that ...

Any idea ??

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

贱贱哒 2024-11-22 03:13:14

除了 musiKk 答案之外,如果您使用 xjc 从 xsd 生成域模型类。
要在所有模型类中添加对父类的引用,您应该:

  1. 创建扩展Unmarshaller.Listener

    的基类

    公共抽象类 BaseClass 扩展了 Unmarshaller.Listener {
        受保护的对象父级;
    
        公共无效 afterUnmarshal(Unmarshaller unmarshaller,对象父级){
            this.parent = 父级;
        }
    
        公共对象 getParent(){
            返回父级;
        }
    }
    
  2. 告诉 xjc 所有模型类都应该通过创建全局 xjc 绑定配置来扩展你的 BaseClass

    ;
        
    
    

In addition to musiKk answer in case you are using xjc to generate domain model classes from xsd.
To add reference to parent class in all model classes you should:

  1. Create base class which extends Unmarshaller.Listener

    public abstract class BaseClass extends Unmarshaller.Listener {
        protected Object parent;
    
        public void afterUnmarshal(Unmarshaller unmarshaller, Object parent)     {
            this.parent = parent;
        }
    
        public Object getParent(){
            return parent;
        }
    }
    
  2. Tell xjc that all model classes should extend your BaseClass by creating global xjc binding configuration

    <jaxb:globalBindings>
        <xjc:superClass name="com.acme.BaseClass" />
    </jaxb:globalBindings>
    
温折酒 2024-11-22 03:13:14
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">   
    <xs:complexType name="A">
    <xs:sequence>
        <xs:element name="b" type="B" minOccurs="0" maxOccurs="unbounded">
        </xs:element>
    </xs:sequence>
    <xs:attribute name="id" type="xs:ID"></xs:attribute>
</xs:complexType>
<xs:complexType name="B">
 <xs:sequence>
    <xs:element name="a" type="A" minOccurs="1" maxOccurs="1"/>
     </xs:sequence>
</xs:complexType>
 <xs:attribute name="id" type="xs:ID"></xs:attribute>
</xs:schema>

试试这个...

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">   
    <xs:complexType name="A">
    <xs:sequence>
        <xs:element name="b" type="B" minOccurs="0" maxOccurs="unbounded">
        </xs:element>
    </xs:sequence>
    <xs:attribute name="id" type="xs:ID"></xs:attribute>
</xs:complexType>
<xs:complexType name="B">
 <xs:sequence>
    <xs:element name="a" type="A" minOccurs="1" maxOccurs="1"/>
     </xs:sequence>
</xs:complexType>
 <xs:attribute name="id" type="xs:ID"></xs:attribute>
</xs:schema>

Try this...

慵挽 2024-11-22 03:13:14

为了使 swarmshine 答案与 org.glassfish.jaxb:jaxb-runtime:jar:2.3.5 一起使用,我做了一些调整:

  • 我必须注释 BaseClass 类和带有 @XmlTransientparent 属性,否则创建 JAXBContext 失败。这是因为我的 XSD 文件中未定义 BaseClass,所以
  • 我不需要扩展 Unmarshaller.Listener。我相信运行时会根据名称和签名自行找到 afterUnmarshal 方法。
package mypackage;

import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
public abstract class BaseClass {

    @XmlTransient
    private BaseClass parent;

    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent){
        if (parent instanceof BaseClass){
            this.parent = (BaseClass) parent;
        }
    }

    public BaseClass getParent() {
        return this.parent;
    }
}

To make swarmshine answer work with org.glassfish.jaxb:jaxb-runtime:jar:2.3.5, I made a few adjustments :

  • I had to annotate the BaseClass class and the parent attribute with @XmlTransient otherwise creating JAXBContext failed. It is because BaseClass is not defined in my XSD file
  • I did not need to extend Unmarshaller.Listener. I believe the runtime finds the afterUnmarshal method by itself, based on the name and the signature.
package mypackage;

import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
public abstract class BaseClass {

    @XmlTransient
    private BaseClass parent;

    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent){
        if (parent instanceof BaseClass){
            this.parent = (BaseClass) parent;
        }
    }

    public BaseClass getParent() {
        return this.parent;
    }
}
墨落画卷 2024-11-22 03:13:13

您可以创建一个方法 void afterUnmarshal (Unmarshaller, Object Parent) 被调用...好吧,在解组并根据需要设置对象树之后。

You can create a method void afterUnmarshal(Unmarshaller, Object parent) that gets called... well, after unmarshalling and set up your object tree as you need it.

下雨或天晴 2024-11-22 03:13:13

注意:我是 EclipseLink JAXB (MOXy) 负责人,以及 JAXB (JSR-222) 专家组成员。

Eclipse JAXB (MOXy) 提供了@XmlInverseReference 扩展来处理此用例。目前它无法由 XJC 生成,必须直接应用于领域模型:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }

class B {
    ...
    @XmlInverseReference(mappedBy="b")
    public A getA() {
    ...
}

了解更多信息

Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB (JSR-222) expert group.

Eclipse JAXB (MOXy) offers the @XmlInverseReference extension to handle this use case. Currently it can not be generated by XJC and must be applied to the domain model directly:

class A {
    ...
    public List<B> getB() { ...}
    ...
   }

class B {
    ...
    @XmlInverseReference(mappedBy="b")
    public A getA() {
    ...
}

For More Information

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文