使用Spring-batch 4.1.2来使用复杂的XML并写入数据库。 使用StaxEventItemReader读取XML数据。
在指定 fragmentRootElementNames 时,我遇到了嵌套元素的问题。
<bean id="productFileItemReader" class="org.springframework.batch.item.xml.StaxEventItemReader" scope="step">
<property name="resource" ref="inputResource" />
<property name="fragmentRootElementNames" value="ProductFeatures,ProductFeaturesDetail,SomeOtherNon-NestedFragmentNames..." />
<property name="unmarshaller" ref="productMarshaller" />
</bean>
<bean id="productMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.xyz.jaxb.ProductFeaturesType</value>
<value>com.xyz.jaxb.ProductFeaturesDetailType</value>
...Some more types
</list>
</property>
</bean>
<bean id="productFileItemProcessor" class="org.springframework.batch.item.support.ClassifierCompositeItemProcessor"
scope="step">
<property name="classifier" ref="prodItemProcessorclassifier" />
</bean>
<bean id="prodItemProcessorclassifier" class="org.springframework.classify.BackToBackPatternClassifier">
<property name="routerDelegate">
<bean class="com.xyz.batch.CustomProdTypeClassifier" />
</property>
<property name="matcherMap">
<map>
<entry key="ProductFeatures" value-ref="prodFeaturesProcessor" />
<entry key="ProductFeaturesDetail" value-ref="prodFeaturesDetailProcessor" />
</map>
</property>
</bean>
<bean id="prodItemWriter" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter"
scope="step">
<property name="classifier" ref="prodItemWriterclassifier" />
</bean>
<bean id="prodItemWriterclassifier" class="org.springframework.classify.BackToBackPatternClassifier">
<property name="routerDelegate">
<bean class="com.xyz.batch.CustomProdTypeClassifier" />
</property>
<property name="matcherMap">
<map>
<entry key="ProductFeaturesDetail" value-ref="prodHibernateItemWriter" />
<entry key="ProductParameters" value-ref="myListItemWriter" />
</map>
</property>
</bean>
<bean id="myListItemWriter" class="com.xyz.writer.ListDelegateItemWriter">
<property name="delegate" ref="prodHibernateItemWriter" />
</bean>
<bean id="prodHibernateItemWriter" class="org.springframework.batch.item.database.HibernateItemWriter">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
这是ItemProcessors的签名
public class ProductFeaturesProcessor implements ItemProcessor<ProductFeaturesType, List<ProductParamEntity>>{}
public class ProductFeaturesDetailProcessor implements ItemProcessor<ProductFeaturesDetailType, ProductFeaturesDetailEntity> {}
XML结构如下-
<ProductFeatures>
<Version>12</Version>
<MessageEN>Welcome</MessageEN>
<MessageFR>Bienvenue</MessageFR>
<ProductFeaturesDetail>
<!-- Some elements here -->
</ProductFeaturesDetail>
<ProductFeaturesDetail>
<!-- Some elements here -->
</ProductFeaturesDetail>
<ProductFeaturesDetail>
<!-- Some elements here -->
</ProductFeaturesDetail>
<ProductFeaturesDetail>
<!-- Some elements here -->
</ProductFeaturesDetail>
</ProductFeatures>
此处,ProductFeatures的minOccurs = 1,maxOccurs = 1。 ProductFeaturesDetail是不受限制的。
每个版本,MessageEN,MessageFR都必须作为记录保留在表A中,该记录具有2列ParamName | ParamValue
每个ProductFeaturesDetail是要保留在表B中的记录。
即这3个元素分别映射到ProductParamEntity(即 ParamName =版本,ParamValue = 12; ParamName = MessageEN, ParamValue = Welcome等。)
逻辑上,ProductFeatures不是直接映射到表,而是数据 存储在2个表中,作为列表和 列出到表PRODUCT_PARAM和 分别为PRODUCT_FEATURES_DETAIL。
这里是对象-JAXB和相应实体
@XmlRootElement(name = "ProductFeatures")
public class ProductFeaturesType {
@XmlElement(name = "Version")
protected String version;
@XmlElement(name = "MessageEN")
protected String messageEN;
@XmlElement(name = "MessageFR")
protected String messageFR;
@XmlElement(name = "ProductFeaturesDetail")
protected List<ProductFeaturesDetailType> prodFeaturesDetail;
}
@Entity
@Table(name="PRODUCT_PARAM")
public class ProductParamsEntity extends BaseEntity implements Serializable {
@Id
@Column(name="PARAM_NAME")
private String paramName;
@Column(name="PARAM_VALUE")
private String paramValue;
}
@Entity
@Table(name="PRODUCT_FEATURES_DETAIL")
public class ProductFeaturesDetailEntity extends BaseEntity implements Serializable {
@Id
@Column(name="PROD_CATEGORY")
private String prodCategory;
//---More attributes ---
}
这是我的作业配置:
<batch:job id="consumeProductFileJob" job-repository="jobRepository" restartable="true">
<batch:step id="validateFile" parent="validateXMLSchema">
<batch:next on="COMPLETED" to="persistData" />
<batch:next on="FAILED" to="notifyException" />
</batch:step>
<batch:step id="persistData">
<batch:tasklet transaction-manager="prodHibernateTransactionManager">
<batch:chunk reader="productFileItemReader" processor="productFileItemProcessor" writer="prodItemWriter" commit-interval="500" >
</batch:chunk>
<batch:transaction-attributes isolation="DEFAULT" propagation="REQUIRED" />
</batch:tasklet>
</batch:step>
<batch:step id="notifyException">
-- Do something---
</batch:step>
</batch:job>
问题::如果我同时将其指定为fragmentRootElementNames,则仅保留ProductFeatures元素的Version,MessageEN,MessageFR 在表A中。 ProductFeaturesDetail被忽略。
如果我仅指定ProductFeaturesDetail,它可以正常工作。但是我不明白 ProductFeatures中的各个元素。
我想要两个元素的数据。实现此目的的方法是什么?
P.S。我正在使用HibernateItemWriter进行持久化。