Spring batch 如何在实现项读取器时读取非重复元素?

Spring batch 如何在实现项读取器时读取非重复元素?,spring-batch,Spring Batch,我有一个场景,我必须读取如下xml: <MovieList language="English"> <Movie>..<Movie> <Movie>..<Movie> </MovieList> .. .. 我必须阅读电影标签,这是一个复杂的对象(标签),并插入到电影表的细节。我已经将fragmentRootElementName设置为电影,并且能够完全读取电影标签。然而,我无法读取language属性,它不是重

我有一个场景,我必须读取如下xml:

<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