1

まず第一に、小さな例です。クラスReferencingEntityは、抽象クラスAbstractEntityへの参照を保持します。このクラスには2つの実装があります。

@XmlRootElement
public abstract class AbstractEntity {

    @XmlID
    private String id;
}

@XmlRootElement
public class EntityImpl1 extends AbstractEntity {

}

@XmlRootElement
public class EntityImpl2 extends AbstractEntity {

}

@XmlRootElement
public class ReferencingEntity {

    @XmlIDREF
    private AbstractEntity entity;
}

ReferencingEntityのインスタンスをマーシャリングすることに問題はありません(具体的なタイプがxmlに存在しないことを除いて)が、xml表現を非マーシャリングしようとすると、具体的な実装を決定するための記述子がありません。

現在、XmlAdapterを使用してすべての非IDフィールドをnullに設定していますが、可能であれば@XmlIDを使用することをお勧めします。何か案は?

更新:JBoss 6.1.0.FinalでRESTEasyを使用しており、プロバイダーは次のようにコンテキストを作成します。

ContextResolver<JAXBContextFinder> resolver = providers.getContextResolver(JAXBContextFinder.class, mediaType);
JAXBContextFinder finder = resolver.getContext(type);
if (finder == null)
{
   if (reader) throw new JAXBUnmarshalException("Could not find JAXBContextFinder for media type: " + mediaType);
   else throw new JAXBMarshalException("Could not find JAXBContextFinder for media type: " + mediaType);
}
JAXBContext context = finder.findCachedContext(type, mediaType, annotations);
4

1 に答える 1

1

以下はあなたの質問に対する私の最初の答えです。あなたのユースケースをよりよく理解するにつれて、それは進化すると思います。

について@XmlID/@XmlIDREF

注釈が付けられたフィールド/プロパティから参照されるすべてのインスタンス@XmlIDREFも、包含を介して参照される必要があります。この例では、以下のクラスを使用します。

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private AbstractEntity abstractEntity;
    private ReferencingEntity referencingEntity;

    public AbstractEntity getAbstractEntity() {
        return abstractEntity;
    }

    public void setAbstractEntity(AbstractEntity abstractEntity) {
        this.abstractEntity = abstractEntity;
    }

    public ReferencingEntity getReferencingEntity() {
        return referencingEntity;
    }

    public void setReferencingEntity(ReferencingEntity referencingEntity) {
        this.referencingEntity = referencingEntity;
    }

}

継承について

JAXB(JSR-222)実装はサブクラスを自動的に検出できないため、がサブクラスをJAXBContext認識していることを確認する必要があります。これを実現する1つの方法は@XmlSeeAlso、親クラスのアノテーションを使用して子クラスを指すことです。

import javax.xml.bind.annotation.*;

@XmlSeeAlso({EntityImpl1.class, EntityImpl2.class})
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class AbstractEntity {

    @XmlID
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

デモコード

デモ

package forum12111815;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum12111815/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        System.out.println(root.getAbstractEntity().getClass());
        System.out.println(root.getAbstractEntity() == root.getReferencingEntity().getEntity());

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

input.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <abstractEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="entityImpl2">
      <id>123</id>
   </abstractEntity>
   <referencingEntity>
      <entity>123</entity>
   </referencingEntity>
</root>

出力

class forum12111815.EntityImpl2
true
<?xml version="1.0" encoding="UTF-8"?>
<root>
   <abstractEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="entityImpl2">
      <id>123</id>
   </abstractEntity>
   <referencingEntity>
      <entity>123</entity>
   </referencingEntity>
</root>

詳細については

于 2012-08-24T15:37:52.217 に答える