异常:使用 EclipseLink JAXB (MOXy) 解组 XML 时"Missing class indicator field from database row [UnmarshalRec



是否有办法使用@XmlDescriminatorNode/@XmlDescrimintatorValue注释解组下一个XML,或任何解决方案:

<assets>
    <asset type="full">
        <data_file role="source">
            <locale name="ru-RU"/>
        </data_file>
        <data_file role="extension">
            <locale name="ru-RU"/>
        </data_file>
        <data_file>
            <locale name="ru-RU"/>
        </data_file>
    </asset>
</assets>

映射类:

@XmlRootElement(name="data_file")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorNode("@role")
public abstract class BaseDataFile implements Serializable {
    @XmlPath("@role")
    @XmlAttribute(name = "role")
    private String role;
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
}
@XmlRootElement(name="data_file")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("source")
public class SourceDataFile extends BaseDataFile {
}
@XmlRootElement(name="data_file")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("source")
public class SourceDataFile extends BaseDataFile {
}
@XmlRootElement(name="data_file")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("extension")
public class SourceDataFile extends BaseDataFile {
}
@XmlRootElement(name="asset")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorNode("@type")
public abstract class BaseAsset implements Serializable {
    @XmlPath("@type")
    @XmlAttribute(name = "type")
    private String type;
    @XmlPath("data_file")
    private List<BaseDataFile> dataFiles;
    public List<BaseDataFile> getDataFiles() {
        return dataFiles;
    }
    public void setDataFiles(List<BaseDataFile> dataFiles) {
        this.dataFiles = dataFiles;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}

如果XML包含如下元素,没有"type"属性,会发生错误:

<data_file>
  <locale name="ru-RU"/>
</data_file>

Thanks in advance

以下内容应该有所帮助:

JAVA模型

超级类(BaseDataFile)

下面是BaseDataFile类的简化版本。由于您已经将XML属性role映射为继承指示符,因此您不需要将其也映射到对象模型中的属性。

import java.io.Serializable;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SourceDataFile.class, ExtensionDataFile.class})
@XmlDiscriminatorNode("@role")
public abstract class BaseDataFile implements Serializable {
}

如果你真的想将role XML属性映射到对象模型中的属性,你应该使用MOXy的@XmlReadOnly属性来防止它被编组到XML文档(它将已经被写为继承指示符)。

import java.io.Serializable;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
import org.eclipse.persistence.oxm.annotations.XmlReadOnly;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SourceDataFile.class, ExtensionDataFile.class})
@XmlDiscriminatorNode("@role")
public abstract class BaseDataFile implements Serializable {
    @XmlAttribute
    @XmlReadOnly
    String role;
}

子类

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("source")
public class SourceDataFile extends BaseDataFile {
}

缺失的继承指示符

基类不是抽象的

如果您的基类(BaseDataFile)不是抽象的,那么如果继承指示符缺失,则会创建基类的一个实例。

基类是抽象的

由于你的基类是抽象的,MOXy抱怨缺少继承指示值:

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-44] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class indicator field from database row [UnmarshalRecordImpl()].
Descriptor: XMLDescriptor(forum15597322.BaseDataFile --> [])
    at org.eclipse.persistence.exceptions.DescriptorException.missingClassIndicatorField(DescriptorException.java:957)
    at org.eclipse.persistence.internal.oxm.XMLRelationshipMappingNodeValue.processChild(XMLRelationshipMappingNodeValue.java:83)
    at org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue.startElement(XMLCompositeCollectionMappingNodeValue.java:184)
    at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.startElement(UnmarshalRecordImpl.java:834)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at org.eclipse.persistence.internal.oxm.record.XMLReader.parse(XMLReader.java:221)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:895)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:388)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:366)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:323)
    at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:367)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:123)
    at forum15597322.Demo.main(Demo.java:23)

忽略错误

JAXB (JSR-222)实现(包括MOXy)报告在对ValidationEventHandler进行编组/解组时遇到的异常;当遇到缺少继承指示符值时,默认的CC_8将出错。下面是一个设置自定义ValidationEventHandler的例子,它通过从handleEvent方法返回true来表示永远不会出错。

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setEventHandler(new ValidationEventHandler() {
        @Override
        public boolean handleEvent(ValidationEvent event) {
            return true;
        }
    });

在把这个答案放在一起时,我发现了以下MOXy错误,由于上面的操作,它将把无效的文本值作为集合中的一个项目。该修复针对的是EclipseLink 2.5.1。

  • http://bugs.eclipse.org/404269

一旦修复,无效条目将被忽略。这就是你想要的行为吗?


查看更多信息

  • http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-moxy-extension.html
  • http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html
  • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html

最新更新