Cree un archivo XML no trivial con StaxEventItemWriter
Necesito volcar el contenido de algunas tablas de base de datos en un archivo XML con esta estructura
<dump>
<table name="tableName1">
<records>
<record>
<first column name>value</first column name>
<second column name>value</second column name>
<third column name>value</third column name>
</record>
<record>...</record>
</records>
</table>
<table name="tableName2">...</table>
</dump>
Se desconoce el número real de registros para cada tabla, por lo que no puedo almacenar todos los datos de una sola tabla en la memoria y volcarlos a XML.
Mi trabajo ahora se define como:
<job id="dump-database-job">
<step id="dumpTables">
<tasklet>
<chunk reader="dumpReader" processor="dumpProcessor" writer="dumpWriter" commit-interval="100" />
</tasklet>
</step>
</job>
<bean name="dumpProcessor" class="RecordBeanToJaxbElementProcessor" />
<bean name="dumpReader" class="CompositeItemReader">
<property name="delegates">
<array>
<ref bean="TABLE_ONE_Reader" />
<ref bean="TABLE_TWO_Reader" />
<ref bean="TABLE_NTH_Reader" />
<!-- Other delegates omitted,one for table,for brevity... -->
</array>
</property>
<property name="name" value="dumpReader" />
</bean>
<bean name="TABLE_ONE_Reader" class="JdbcCursorItemReader">
<property name="rowMapper">
<bean name="rowMapper" class="RecordBeanRowMapper">
<property name="tableName=" value="TABLE_ONE" />
</bean>
</property>
<!--other mandatory property omitted -->
</bean>
<bean name="dumpWriter" class="StaxEventItemWriter" scope="step">
<property name="resource" value="file:#{jobParameters['outfile']}" />
<property name="shouldDeleteIfEmpty" value="true" />
<property name="marshaller" ref="marshaller" />
<property name="overwriteOutput" value="true" />
<property name="rootTagName" value="dump" />
</bean>
<bean name="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="supportJaxbElementClass" value="true" />
<property name="classesToBeBound">
<array>
<value>RecordBean</value>
</array>
</property>
</bean>
public class RecordBeanRowMapper implements RowMapper<RecordBean> {
final static RowMapper<Map<String, Object>> columnMapRowMapper = new ColumnMapRowMapper();
private String tableName;
public void setTableName(String tableName) {
this.tableName = tableName;
}
@Override
public RecordBean mapRow(ResultSet rs, int rowNum) throws SQLException {
final RecordBean b = new RecordBean();
b.setTableName(tableName);
b.setColumnValues(Maps.transformValues(columnMapRowMapper.mapRow(rs, rowNum), new Function<Object, String>() {
@Override
public String apply(Object input) {
return (input == null ? "NULL" : input.toString();
}
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace="")
class RecordBean {
private String tableName;
@XmlJavaTypeAdapter
/* Entries are written using an adapter to write data as
* <key>value</key>
* <key>value</key>
* ...
*/
public Map<String,String> entries = new HashMap<String,String>();
}
/* Use to build item node name using dynamic tableName as
* <tableName>
* <key>value</key>
* <key>value</key>
* </tableName>
*/
public class RecordBeanToJaxbElementProcessor implements ItemProcessor<RecordBean, JAXBElement<?>> {
@Override
public JAXBElement<?> process(RecordBean item) throws Exception {
return new JAXBElement<RecordBean>(new QName(item.getTableName()), RecordBean.class, item);
}
}
Este trabajo está incompleto y no cubre mis necesidades porque el resultado parece
<?xml version="1.0" encoding="UTF-8"?>
<dump>
<!-- First record of table TABLE_ONE -->
<TABLE_ONE>
<code>Code one</code>
<description>A record</description>
<agomappedtable>xyz</agomappedtable>
<enumcode>NULL</enumcode>
<is_persistent>false</is_persistent>
<keep_history_data>false</keep_history_data>
</TABLE_ONE>
<!-- Other tons from TABLE_ONE -->
<!-- First record of table TABLE_TWO -->
<TABLE_TWO>
<code>Code 2</code>
<description>Another record</description>
<his_name>no_name</his_name>
</TABLE_TWO>
<!-- Other tons from TABLE_TWO -->
<!-- More tables... -->
</dump>
Creo que tengo que enriquecer los componentes del escritor y / o del mariscal para lograr mi objetivo, pero no he encontrado una buena manera de proceder :(
Mi pregunta es:
¿Cómo construir una estructura XML compleja como se describe al principio y hacer que el trabajo se pueda reiniciar completamente y con poco uso de memoria?