这个让我难过。我有一个针对Java 1.8.0.77运行的Java String Batch应用程序,没有任何错误。它读取XML文件并将其完美地写入数据库。
更新到JDK 1.8.0.162之后,即使将日志记录设置为DEBUG,阅读器也无法正常工作并且不会发送任何错误消息。改回Java 1.8.0.77可解决此问题。尽管我们的服务器正在运行162,所以我必须在162中进行这项工作。
这是读者:
@Bean
ItemReader<Product> reviewItemReader() {
StaxEventItemReader<Product> xmlFileReader = new StaxEventItemReader<>();
xmlFileReader.setResource(new FileSystemResource(this.fileName));
xmlFileReader.setFragmentRootElementName("Product");
Jaxb2Marshaller feedMarshaller = new Jaxb2Marshaller();
feedMarshaller.setClassesToBeBound(Product.class);
xmlFileReader.setUnmarshaller(feedMarshaller);
return xmlFileReader;
}
当我针对Java 1.0.8.77运行它时,我得到了完整的产品记录,并且所有子类都被文件中的数据填充回去。当我针对Java 1.0.8.162运行它时,我只获得了产品标签上的3个属性,而里面没有任何字段。
XML看起来像:
...
<Product id="asdsada" removed="false" disabled="true">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
...
</Product>
<Product id="zxcvzxcvxcv" removed="true" disabled="false">
<Descriptoin> Blah blah blah</Descriptoin>
<UPCs>
<UPC> 123222423432</UPC>
</UPCs>
<Rating>5</Rating>
<Name>name here</Name>
<Categories>
<Category> Cat 1 </Category>
<Category> Cat 2 </Category>
<Category> Cat 3 </Category>
</Categories>
....
</Product>
产品类别是这样的
@XmlRootElement(name = "Product", namespace = "FOO POWER")
public class Product {
@XmlAttribute(name = "removed")
public String removed;
@XmlAttribute(name = "disabled")
public String disabled;
@XmlAttribute(name = "id")
public String id;
public String Name;
public String Rating;
public UPCs UPCs;
public Brand Brand;
...
同样,它在1.8.0.77中完全没有问题。在测试中,我已经通过它运行了数百万条记录。这些相同的记录在1.8.0.162中运行时失败
Someone asked to see what a child class looks like. They are pretty much like this:
public class Brand {
public String Name;
public Attributes Attributes;
public String ExternalId;
public String disabled;
...
最佳答案
我今年早些时候遇到了类似的问题。我正在将一个项目从Java 1.8.0_92升级到1.8.0_152,并且一些与1.8.0_92一起使用的JAXB解组已停止了与1.8.0_152一起使用。我在下面的回答中给出的更多内容是实验结果,而不是参考文档,因为我一直在努力寻找相关文档来支持我的发现。如果其他人可以找到相关的文档,我将很感兴趣。
我的理解是,如果Java类中的字段或属性没有@XmlElement
批注,则JAXB视情况将其视作具有注释@XmlElement(name = "fieldName")
或@XmlElement(name = "propertyName")
的字段或属性。因此,例如,您的Product
类中未注释的字段将被如下处理:
@XmlElement(name = "Name")
public String Name;
@XmlElement(name = "Rating")
public String Rating;
@XmlElement(name = "UPCs")
public UPCs UPCs;
@XmlElement(name = "Brand")
public Brand Brand;
此外,在Java 8更新101和111之间,JAXB中处理名称空间的方式发生了变化。 Java 8更新101允许元素仅在本地名称上匹配,而不管名称空间如何,但是从更新111开始,元素名称空间也必须匹配。如果不指定名称空间(特别是如果根本不指定
@XmlElement
批注),则使用默认名称空间。Product
元素的子元素不在默认名称空间中,因此它们不再与上面的@XmlElement
注释匹配。但是,例如,尝试将xmlns=""
添加到Rating
元素。您应该找到该产品的等级。因此,一种可能的解决方案是向所有子元素添加
@XmlElement
批注,其中包括命名空间。这就是我需要解决的问题:我已经有必要的@XmlElement
批注,我只需要向一个这样的批注添加名称空间。但是,我怀疑您有更多的子元素,并且您指定的样本文档已从更大的真实文档中删除。考虑到这一点,创建带有相关注释的package-info.java
文件并将其放入包含POJO的包中可能会更快一些(希望它们都在同一个包中):@XmlSchema(
namespace = "FOO POWER",
elementFormDefault = XmlNsForm.QUALIFIED)
package your.package.name.here;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
我将其添加到为测试您的代码而创建的一个小型Java项目中,发现解组似乎可以正常工作。
Product
类中的子属性正在使用XML文档中的值填充。我想到了使用this page中的package-info.java
文件的想法。