例外:“数据库行 [UnmarshalRecordImpl()] 中缺少类指示符字段."使用 EclipseLink JAXB (MOXy) 解组 XML 时
是否可以通过 @XmlDescriminatorNode/@XmlDescrimintatorValue 注释解组下一个 XML,或任何解决方法:
Is it any way to unmarshalling with @XmlDescriminatorNode/@XmlDescrimintatorValue annotations next XML, or any workaround:
<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" 属性,则会发生错误:
The error occures if XML containes element as below, without "type" attribute:
<data_file>
<locale name="ru-RU"/>
</data_file>
提前致谢
推荐答案
以下应该会有所帮助:
JAVA 模型
超类(BaseDataFile
)
下面是您的 BaseDataFile
类的简化版本.由于您已将 XML 属性 role
映射为继承指示符,因此您无需将其也映射到对象模型中的属性.
Below is a simplified version of your BaseDataFile
class. Since you have mapped the XML attribute role
as the inheritance indicator you do not need to also map it to a property in your object model.
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 文档(它已经写成继承指示符了).
If you really want to map the role
XML attribute to a property in your object model you should use MOXy's @XmlReadOnly
property to prevent it being marshalled to the XML document (it will already be wriiten as the inheritance indicator).
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;
}
子类(SourceDataFile
)
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("source")
public class SourceDataFile extends BaseDataFile {
}
<小时>
缺少继承指示符
基类不是抽象的
如果您的基类 (BaseDataFile
) 不是抽象的,那么如果缺少继承指示符,则会创建一个基类的实例.
If your base class (BaseDataFile
) had not been abstract then if the inheritance indicator was missing an instance of the base class would have been created.
基类是抽象的
由于您的基类是抽象的,MOXy 抱怨缺少继承指示符值:
Since your base class is abstract MOXy complained about the missing inheritance indicator value:
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) 实现包括在编组/解组到 ValidationEventHandler
期间遇到的 MOXy 报告异常,当遇到缺少继承指示符值时,默认会出错.下面是设置自定义 ValidationEventHandler
的示例,该示例通过从 handleEvent
方法返回 true
来表示永不出错.
JAXB (JSR-222) implementations including MOXy report exceptions encountered during marshalling/unmarshaling to a ValidationEventHandler
the default one will error out when a missing inheritance indicator value is encountered. Below is an example of setting a custom ValidationEventHandler
that says never error out by returning true
from the handleEvent
method.
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
@Override
public boolean handleEvent(ValidationEvent event) {
return true;
}
});
将这个答案放在一起时,我发现了以下 MOXy 错误,由于执行上述操作,该错误会将无效的文本值作为集合中的一个项目.该修复针对 EclipseLink 2.5.1.
While putting this answer together I found the following MOXy bug which as a result of doing the above will put an invalid text value as an item in the collection. The fix is targeted against EclipseLink 2.5.1.
- http://bugs.eclipse.org/404269
一旦修复进入无效条目,将被忽略.这是您正在寻找的行为吗?
Once that fix goes in the invalid entry will just be ignored. Is this the behaviour you are looking for?
更多信息
- 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
相关文章