Spring batch 如何在实现项读取器时读取非重复元素?
我有一个场景,我必须读取如下xml:Spring batch 如何在实现项读取器时读取非重复元素?,spring-batch,Spring Batch,我有一个场景,我必须读取如下xml: <MovieList language="English"> <Movie>..<Movie> <Movie>..<Movie> </MovieList> .. .. 我必须阅读电影标签,这是一个复杂的对象(标签),并插入到电影表的细节。我已经将fragmentRootElementName设置为电影,并且能够完全读取电影标签。然而,我无法读取language属性,它不是重
<MovieList language="English">
<Movie>..<Movie>
<Movie>..<Movie>
</MovieList>
..
..
我必须阅读电影标签,这是一个复杂的对象(标签),并插入到电影表的细节。我已经将fragmentRootElementName设置为电影,并且能够完全读取电影标签。然而,我无法读取language属性,它不是重复标记
我应该如何获取非重复标记的详细信息?我应该自己解析XML来读取它吗?或者我应该再写一个fragmentRootElementName来读取language属性吗
项目阅读器的配置如下所示:
<bean id="movieReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="unmarshaller" ref="marshaller" />
<property name="fragmentRootElementName" value="Movie" />
<property name="resource" value="file:#{jobParameters['inputFile']}" />
</bean>
好的,简单的方法是定义您的fragmentRootElementName=MovieList,但如果您的MovieList可以包含数百万部电影,我想这不是一个好主意 我有一个类似的问题,我需要知道我的fragmentRootElementName的父标记 因此,我们创建了一个CustomStateVentitemReader,它扩展了原始StateVentitemReader 我们添加了一个属性parentElement,您可以在配置中设置它。我们重写moveCursorToNextFragment()和doRead()方法来处理这个问题 现在我的代码并不能完全满足你的需要,但是我修改了它,它看起来很有效
protected boolean moveCursorToNextFragment(XMLEventReader reader) {
try {
while (true) {
while (reader.peek() != null && !reader.peek().isStartElement()) {
reader.nextEvent();
}
if (reader.peek() == null) {
return false;
}
XMLEvent ev = reader.peek();
QName startElementName = ((StartElement) ev).getName();
// Take note of current parent element. Must be one of
// ParentTags
String tmp = startElementName.getLocalPart();
for (ParentTags aTag : ParentTags.values()) {
if (aTag.toString().equals(tmp)) {
currentParent = tmp;
Attribute attr = ((StartElement) ev)
.getAttributeByName(new QName("Language"));
if (null != attr) {
parentAttribute = attr.getValue();
}
break;
}
}
if (startElementName.getLocalPart().equals(
fragmentRootElementName)) {
if ((fragmentRootElementNameSpace == null && parentElement
.equals(currentParent))
|| startElementName.getNamespaceURI().equals(
fragmentRootElementNameSpace)) {
return true;
}
}
reader.nextEvent();
}
} catch (XMLStreamException e) {
throw new DataAccessResourceFailureException(
"Error while reading from event reader", e);
}
}
因此,基本上,如果您查看原始StateVentReader的代码,您将看到它通过xml文件的所有元素。每次它向您的rootElement获取一个名为=的元素时,它都会返回true,而doRead会将其解组并返回关联的对象
现在,我们只添加一些代码来查找给定的父元素。我使用了一个名为ParentTags的枚举,因为我的XML比较复杂,但是您只能比较配置中定义的新parentElement的名称
因此,如果实际元素与parentElement相等,只需将其分配给currentParent并尝试获取属性。如果不为null,则将其指定给parentAttribute属性
然后在doRead()方法中,可以访问parentAttribute属性并在域对象中设置它
protected T doRead() throws Exception {
if (noInput) {
return null;
}
T item = null;
if (moveCursorToNextFragment(fragmentReader)) {
fragmentReader.markStartFragment();
@SuppressWarnings("unchecked")
T mappedFragment = (T) unmarshaller.unmarshal(StaxUtils
.createStaxSource(fragmentReader));
item = mappedFragment;
logger.info("Item read : " + item);
currentIndex = cIndex.getAndIncrement();
T p = (T) item;
if (p instanceof myDomainObj) {
myDomainObj pp = (myDomainObj) p;
logger.info(pp);
logger.info("attribute parent = " + parentAttribute);
pp.setLanguage(parentAttribute);
}
fragmentReader.markFragmentProcessed();
}
return item;
}
我希望这足够清楚
祝你好运和问候你正在使用StatxeventitemReader吗?是的。我正在使用StateVentitemReader。谢谢你的回答。我是SpringBatch的新手,我想确认SpringBatch是否可以从框架中提供一些东西来处理这种情况。看起来SpringBatch没有提供处理这种情况的功能。感谢您详细介绍我如何为自己创建自定义阅读器。将尝试通过编写自定义读取器来解决此问题…欢迎使用spring batch;-)您可能可以使用SpringBatch执行与批处理相关的任何操作。。。有时,您只需要在框架内部挖掘一点。这是一个伟大的+当这个框架是开源的:-D